summaryrefslogtreecommitdiff
path: root/internal/mapr/selectcondition.go
blob: 45fc16b35d32ef8c8969e109765323fff3505cc7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package mapr

import (
	"errors"
	"fmt"
	"strings"
)

// AggregateOperation is to specify the aggregate operation type.
type AggregateOperation int

// Aggregate operation types
const (
	UndefAggregateOperation AggregateOperation = iota
	Count                   AggregateOperation = iota
	Sum                     AggregateOperation = iota
	Min                     AggregateOperation = iota
	Max                     AggregateOperation = iota
	Last                    AggregateOperation = iota
	Avg                     AggregateOperation = iota
	Len                     AggregateOperation = iota
)

// Represents a parsed "select" clause, used by mapr.Query.
type selectCondition struct {
	Field        string
	FieldStorage string
	Operation    AggregateOperation
}

func (sc selectCondition) String() string {
	return fmt.Sprintf("selectCondition(Field:%s,FieldStorage:%s,Operation:%v)",
		sc.Field,
		sc.FieldStorage,
		sc.Operation)
}

func makeSelectConditions(tokens []token) ([]selectCondition, error) {
	var sel []selectCondition
	// Parse select aggregation, e.g. sum(foo)
	parse := func(token token) (selectCondition, error) {
		var sc selectCondition
		tokenStr := token.str

		if !strings.Contains(tokenStr, "(") && !strings.Contains(tokenStr, ")") {
			sc.Field = tokenStr
			sc.FieldStorage = tokenStr
			sc.Operation = Last
			return sc, nil
		}

		a := strings.Split(tokenStr, "(")
		if len(a) != 2 {
			return sc, errors.New(invalidQuery + "Can't parse 'select' aggregation: " +
				token.str)
		}
		agg := a[0] // Aggregation, e.g. 'sum'

		b := strings.Split(a[1], ")")
		if len(b) != 2 {
			return sc, errors.New(invalidQuery + "Can't parse 'select' field name " +
				"from aggregation: " + token.str)
		}
		sc.Field = b[0]            // Field name, e.g. 'foo'
		sc.FieldStorage = tokenStr // e.g. 'sum(foo)'

		switch agg {
		case "count":
			sc.Operation = Count
		case "sum":
			sc.Operation = Sum
		case "min":
			sc.Operation = Min
		case "max":
			sc.Operation = Max
		case "last":
			sc.Operation = Last
		case "avg":
			sc.Operation = Avg
		case "len":
			sc.Operation = Len
		default:
			return sc, errors.New(invalidQuery +
				"Unknown aggregation in 'select' clause: " + agg)
		}
		return sc, nil
	}

	for _, token := range tokens {
		sc, err := parse(token)
		if err != nil {
			return nil, err
		}
		sel = append(sel, sc)
	}
	return sel, nil
}