github.com/m3db/m3@v1.5.0/src/query/functions/tag/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 tag
    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  // Applies the given transform to block tags and series tags.
    33  type tagTransformFunc func(
    34  	block.Metadata,
    35  	[]block.SeriesMeta,
    36  ) (block.Metadata, []block.SeriesMeta)
    37  
    38  // NewTagOp creates a new tag transform operation.
    39  func NewTagOp(
    40  	opType string,
    41  	params []string,
    42  ) (parser.Params, error) {
    43  	var (
    44  		fn  tagTransformFunc
    45  		err error
    46  	)
    47  
    48  	switch opType {
    49  	case TagJoinType:
    50  		fn, err = makeTagJoinFunc(params)
    51  	case TagReplaceType:
    52  		fn, err = makeTagReplaceFunc(params)
    53  	default:
    54  		return nil, fmt.Errorf("operator not supported: %s", opType)
    55  	}
    56  
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  
    61  	return newBaseOp(opType, fn), nil
    62  }
    63  
    64  // baseOp stores required properties for the baseOp.
    65  type baseOp struct {
    66  	opType string
    67  	tagFn  tagTransformFunc
    68  }
    69  
    70  func (o baseOp) OpType() string {
    71  	return o.opType
    72  }
    73  
    74  func (o baseOp) String() string {
    75  	return fmt.Sprintf("type: %s", o.OpType())
    76  }
    77  
    78  // Node creates a tag execution node.
    79  func (o baseOp) Node(
    80  	controller *transform.Controller,
    81  	_ transform.Options,
    82  ) transform.OpNode {
    83  	return &baseNode{
    84  		op:         o,
    85  		controller: controller,
    86  	}
    87  }
    88  
    89  func newBaseOp(opType string, tagFn tagTransformFunc) baseOp {
    90  	return baseOp{
    91  		opType: opType,
    92  		tagFn:  tagFn,
    93  	}
    94  }
    95  
    96  type baseNode struct {
    97  	op         baseOp
    98  	controller *transform.Controller
    99  }
   100  
   101  func (n *baseNode) Params() parser.Params {
   102  	return n.op
   103  }
   104  
   105  func (n *baseNode) Process(
   106  	queryCtx *models.QueryContext,
   107  	ID parser.NodeID,
   108  	b block.Block,
   109  ) error {
   110  	return transform.ProcessSimpleBlock(n, n.controller, queryCtx, ID, b)
   111  }
   112  
   113  func (n *baseNode) ProcessBlock(
   114  	queryCtx *models.QueryContext,
   115  	ID parser.NodeID,
   116  	b block.Block,
   117  ) (block.Block, error) {
   118  	it, err := b.StepIter()
   119  	if err != nil {
   120  		return nil, err
   121  	}
   122  
   123  	meta := b.Meta()
   124  	seriesMeta := it.SeriesMeta()
   125  	meta, seriesMeta = n.op.tagFn(meta, seriesMeta)
   126  	lazyOpts := block.NewLazyOptions().
   127  		SetMetaTransform(
   128  			func(block.Metadata) block.Metadata { return meta },
   129  		).
   130  		SetSeriesMetaTransform(
   131  			func([]block.SeriesMeta) []block.SeriesMeta { return seriesMeta },
   132  		)
   133  
   134  	return block.NewLazyBlock(b, lazyOpts), nil
   135  }