github.com/muhammadn/cortex@v1.9.1-0.20220510110439-46bb7000d03d/pkg/querier/astmapper/astmapper.go (about)

     1  package astmapper
     2  
     3  import (
     4  	"github.com/pkg/errors"
     5  	"github.com/prometheus/prometheus/promql/parser"
     6  )
     7  
     8  // ASTMapper is the exported interface for mapping between multiple AST representations
     9  type ASTMapper interface {
    10  	Map(node parser.Node) (parser.Node, error)
    11  }
    12  
    13  // MapperFunc is a function adapter for ASTMapper
    14  type MapperFunc func(node parser.Node) (parser.Node, error)
    15  
    16  // Map applies a mapperfunc as an ASTMapper
    17  func (fn MapperFunc) Map(node parser.Node) (parser.Node, error) {
    18  	return fn(node)
    19  }
    20  
    21  // MultiMapper can compose multiple ASTMappers
    22  type MultiMapper struct {
    23  	mappers []ASTMapper
    24  }
    25  
    26  // Map implements ASTMapper
    27  func (m *MultiMapper) Map(node parser.Node) (parser.Node, error) {
    28  	var result parser.Node = node
    29  	var err error
    30  
    31  	if len(m.mappers) == 0 {
    32  		return nil, errors.New("MultiMapper: No mappers registered")
    33  	}
    34  
    35  	for _, x := range m.mappers {
    36  		result, err = x.Map(result)
    37  		if err != nil {
    38  			return nil, err
    39  		}
    40  	}
    41  	return result, nil
    42  
    43  }
    44  
    45  // Register adds ASTMappers into a multimapper.
    46  // Since registered functions are applied in the order they're registered, it's advised to register them
    47  // in decreasing priority and only operate on nodes that each function cares about, defaulting to CloneNode.
    48  func (m *MultiMapper) Register(xs ...ASTMapper) {
    49  	m.mappers = append(m.mappers, xs...)
    50  }
    51  
    52  // NewMultiMapper instaniates an ASTMapper from multiple ASTMappers
    53  func NewMultiMapper(xs ...ASTMapper) *MultiMapper {
    54  	m := &MultiMapper{}
    55  	m.Register(xs...)
    56  	return m
    57  }
    58  
    59  // CloneNode is a helper function to clone a node.
    60  func CloneNode(node parser.Node) (parser.Node, error) {
    61  	return parser.ParseExpr(node.String())
    62  }
    63  
    64  // NodeMapper either maps a single AST node or returns the unaltered node.
    65  // It also returns a bool to signal that no further recursion is necessary.
    66  // This is helpful because it allows mappers to only implement logic for node types they want to change.
    67  // It makes some mappers trivially easy to implement
    68  type NodeMapper interface {
    69  	MapNode(node parser.Node) (mapped parser.Node, finished bool, err error)
    70  }
    71  
    72  // NodeMapperFunc is an adapter for NodeMapper
    73  type NodeMapperFunc func(node parser.Node) (parser.Node, bool, error)
    74  
    75  // MapNode applies a NodeMapperFunc as a NodeMapper
    76  func (f NodeMapperFunc) MapNode(node parser.Node) (parser.Node, bool, error) {
    77  	return f(node)
    78  }
    79  
    80  // NewASTNodeMapper creates an ASTMapper from a NodeMapper
    81  func NewASTNodeMapper(mapper NodeMapper) ASTNodeMapper {
    82  	return ASTNodeMapper{mapper}
    83  }
    84  
    85  // ASTNodeMapper is an ASTMapper adapter which uses a NodeMapper internally.
    86  type ASTNodeMapper struct {
    87  	NodeMapper
    88  }
    89  
    90  // Map implements ASTMapper from a NodeMapper
    91  func (nm ASTNodeMapper) Map(node parser.Node) (parser.Node, error) {
    92  	node, fin, err := nm.MapNode(node)
    93  
    94  	if err != nil {
    95  		return nil, err
    96  	}
    97  
    98  	if fin {
    99  		return node, nil
   100  	}
   101  
   102  	switch n := node.(type) {
   103  	case nil:
   104  		// nil handles cases where we check optional fields that are not set
   105  		return nil, nil
   106  
   107  	case parser.Expressions:
   108  		for i, e := range n {
   109  			mapped, err := nm.Map(e)
   110  			if err != nil {
   111  				return nil, err
   112  			}
   113  			n[i] = mapped.(parser.Expr)
   114  		}
   115  		return n, nil
   116  
   117  	case *parser.AggregateExpr:
   118  		expr, err := nm.Map(n.Expr)
   119  		if err != nil {
   120  			return nil, err
   121  		}
   122  		n.Expr = expr.(parser.Expr)
   123  		return n, nil
   124  
   125  	case *parser.BinaryExpr:
   126  		lhs, err := nm.Map(n.LHS)
   127  		if err != nil {
   128  			return nil, err
   129  		}
   130  		n.LHS = lhs.(parser.Expr)
   131  
   132  		rhs, err := nm.Map(n.RHS)
   133  		if err != nil {
   134  			return nil, err
   135  		}
   136  		n.RHS = rhs.(parser.Expr)
   137  		return n, nil
   138  
   139  	case *parser.Call:
   140  		for i, e := range n.Args {
   141  			mapped, err := nm.Map(e)
   142  			if err != nil {
   143  				return nil, err
   144  			}
   145  			n.Args[i] = mapped.(parser.Expr)
   146  		}
   147  		return n, nil
   148  
   149  	case *parser.SubqueryExpr:
   150  		mapped, err := nm.Map(n.Expr)
   151  		if err != nil {
   152  			return nil, err
   153  		}
   154  		n.Expr = mapped.(parser.Expr)
   155  		return n, nil
   156  
   157  	case *parser.ParenExpr:
   158  		mapped, err := nm.Map(n.Expr)
   159  		if err != nil {
   160  			return nil, err
   161  		}
   162  		n.Expr = mapped.(parser.Expr)
   163  		return n, nil
   164  
   165  	case *parser.UnaryExpr:
   166  		mapped, err := nm.Map(n.Expr)
   167  		if err != nil {
   168  			return nil, err
   169  		}
   170  		n.Expr = mapped.(parser.Expr)
   171  		return n, nil
   172  
   173  	case *parser.EvalStmt:
   174  		mapped, err := nm.Map(n.Expr)
   175  		if err != nil {
   176  			return nil, err
   177  		}
   178  		n.Expr = mapped.(parser.Expr)
   179  		return n, nil
   180  
   181  	case *parser.NumberLiteral, *parser.StringLiteral, *parser.VectorSelector, *parser.MatrixSelector:
   182  		return n, nil
   183  
   184  	default:
   185  		panic(errors.Errorf("nodeMapper: unhandled node type %T", node))
   186  	}
   187  }