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 }