github.com/m3db/m3@v1.5.0/src/query/functions/scalar/scalar.go (about)

     1  // Copyright (c) 2018 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package scalar
    22  
    23  import (
    24  	"github.com/m3db/m3/src/query/block"
    25  	"github.com/m3db/m3/src/query/executor/transform"
    26  	"github.com/m3db/m3/src/query/models"
    27  	"github.com/m3db/m3/src/query/parser"
    28  	"github.com/m3db/m3/src/query/util/logging"
    29  
    30  	"go.uber.org/zap"
    31  )
    32  
    33  const (
    34  	// ScalarType is a scalar series.
    35  	ScalarType = "scalar"
    36  
    37  	// VectorType is a vector series.
    38  	VectorType = "vector"
    39  
    40  	// TimeType returns the number of seconds since January 1, 1970 UTC.
    41  	//
    42  	// NB: this does not actually return the current time, but the time at
    43  	// which the expression is to be evaluated.
    44  	TimeType = "time"
    45  )
    46  
    47  // ScalarOp is a scalar operation representing a constant.
    48  type ScalarOp struct {
    49  	val        float64
    50  	tagOptions models.TagOptions
    51  }
    52  
    53  // Value is the constant value for thes scalar operation.
    54  func (o ScalarOp) Value() float64 {
    55  	return o.val
    56  }
    57  
    58  // OpType is the operation type of the scalar operation.
    59  func (o ScalarOp) OpType() string {
    60  	return ScalarType
    61  }
    62  
    63  // String is the string representation of the scalar operation.
    64  func (o ScalarOp) String() string {
    65  	return "type: scalar"
    66  }
    67  
    68  // Node returns this scalar operation's execution node.
    69  func (o ScalarOp) Node(
    70  	controller *transform.Controller,
    71  	opts transform.Options,
    72  ) parser.Source {
    73  	return &scalarNode{
    74  		op:         o,
    75  		controller: controller,
    76  		opts:       opts,
    77  	}
    78  }
    79  
    80  // NewScalarOp creates an operation that yields a scalar source.
    81  func NewScalarOp(
    82  	val float64,
    83  	tagOptions models.TagOptions,
    84  ) (parser.Params, error) {
    85  	return &ScalarOp{
    86  		val:        val,
    87  		tagOptions: tagOptions,
    88  	}, nil
    89  }
    90  
    91  // scalarNode is the execution node for time source.
    92  type scalarNode struct {
    93  	op         ScalarOp
    94  	controller *transform.Controller
    95  	opts       transform.Options
    96  }
    97  
    98  // Execute runs the scalar source's pipeline.
    99  func (n *scalarNode) Execute(queryCtx *models.QueryContext) error {
   100  	meta := block.Metadata{
   101  		Bounds:         n.opts.TimeSpec().Bounds(),
   102  		Tags:           models.NewTags(0, n.op.tagOptions),
   103  		ResultMetadata: block.NewResultMetadata(),
   104  	}
   105  
   106  	block := block.NewScalar(n.op.val, meta)
   107  	if n.opts.Debug() {
   108  		// Ignore any errors
   109  		iter, _ := block.StepIter()
   110  		if iter != nil {
   111  			logging.WithContext(queryCtx.Ctx, n.opts.InstrumentOptions()).
   112  				Info("scalar node", zap.Any("meta", block.Meta()))
   113  		}
   114  	}
   115  
   116  	if err := n.controller.Process(queryCtx, block); err != nil {
   117  		block.Close()
   118  		// Fail on first error
   119  		return err
   120  	}
   121  
   122  	block.Close()
   123  	return nil
   124  }