github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/query/functions/linear/base.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 linear
    22  
    23  import (
    24  	"fmt"
    25  
    26  	"github.com/m3db/m3/src/query/block"
    27  	"github.com/m3db/m3/src/query/executor/transform"
    28  	"github.com/m3db/m3/src/query/models"
    29  	"github.com/m3db/m3/src/query/parser"
    30  )
    31  
    32  var emptyOp = BaseOp{}
    33  
    34  // BaseOp stores required properties for logical operations.
    35  type BaseOp struct {
    36  	operatorType string
    37  	processorFn  makeProcessor
    38  }
    39  
    40  func (o BaseOp) OpType() string {
    41  	return o.operatorType
    42  }
    43  
    44  func (o BaseOp) String() string {
    45  	return fmt.Sprintf("type: %s", o.OpType())
    46  }
    47  
    48  func (o BaseOp) Node(
    49  	controller *transform.Controller,
    50  	_ transform.Options,
    51  ) transform.OpNode {
    52  	return &baseNode{
    53  		controller: controller,
    54  		op:         o,
    55  		processor:  o.processorFn(o, controller),
    56  	}
    57  }
    58  
    59  type baseNode struct {
    60  	op         BaseOp
    61  	controller *transform.Controller
    62  	processor  Processor
    63  }
    64  
    65  func (c *baseNode) Params() parser.Params {
    66  	return c.op
    67  }
    68  
    69  func (c *baseNode) Process(
    70  	queryCtx *models.QueryContext,
    71  	ID parser.NodeID,
    72  	b block.Block,
    73  ) error {
    74  	return transform.ProcessSimpleBlock(c, c.controller, queryCtx, ID, b)
    75  }
    76  
    77  func (c *baseNode) ProcessBlock(
    78  	queryCtx *models.QueryContext,
    79  	ID parser.NodeID,
    80  	b block.Block,
    81  ) (block.Block, error) {
    82  	stepIter, err := b.StepIter()
    83  	if err != nil {
    84  		return nil, err
    85  	}
    86  
    87  	builder, err := c.controller.BlockBuilder(queryCtx,
    88  		b.Meta(), stepIter.SeriesMeta())
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  
    93  	if err := builder.AddCols(stepIter.StepCount()); err != nil {
    94  		return nil, err
    95  	}
    96  
    97  	for index := 0; stepIter.Next(); index++ {
    98  		step := stepIter.Current()
    99  		values := c.processor.Process(step.Values())
   100  		for _, value := range values {
   101  			if err := builder.AppendValue(index, value); err != nil {
   102  				return nil, err
   103  			}
   104  		}
   105  	}
   106  
   107  	if err = stepIter.Err(); err != nil {
   108  		return nil, err
   109  	}
   110  
   111  	return builder.Build(), nil
   112  }
   113  
   114  func (c *baseNode) Meta(meta block.Metadata) block.Metadata {
   115  	return meta
   116  }
   117  
   118  func (c *baseNode) SeriesMeta(metas []block.SeriesMeta) []block.SeriesMeta {
   119  	return metas
   120  }
   121  
   122  // makeProcessor is a way to create a transform.
   123  type makeProcessor func(op BaseOp, controller *transform.Controller) Processor
   124  
   125  // Processor is implemented by the underlying transforms.
   126  // todo: remove public visibility
   127  type Processor interface {
   128  	Process(values []float64) []float64
   129  }