/
aql_query_result.go
122 lines (107 loc) · 3.45 KB
/
aql_query_result.go
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Copyright (c) 2017-2018 Uber Technologies, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package common
const (
MatrixDataKey = "matrixData"
HeadersKey = "headers"
)
// AQLQueryResult represents final result of one AQL query
//
// It has 2 possible formats:
// Time series result format:
// One dimension on each layer:
// - there is always an outermost time dimension. it stores the start time of
// the bucket/duration (in seconds since Epoch).
// - after the time dimension, there could be zero or more layers of additional
// dimensions (all values are represented as strings). a special "NULL" string
/// is used to represent NULL values.
// - there is always a single measure, and the measure type is either float64
// or nil (not *float64);
//
// Non aggregate query result format:
// - there will be a "headers" key, value will be a list of column names
// - there will be a "matrixData" key, value will be a 2d arary of values (row formated)
//
// user should use it as only 1 of the 2 formats consistently
type AQLQueryResult map[string]interface{}
// ===== Time series result methods start =====
// Set measure value for dimensions
func (r AQLQueryResult) Set(dimValues []*string, measureValue *float64) {
null := NULLString
var current map[string]interface{} = r
for i, dimValue := range dimValues {
if dimValue == nil {
dimValue = &null
}
if i == len(dimValues)-1 {
if measureValue == nil {
current[*dimValue] = nil
} else {
current[*dimValue] = *measureValue
}
} else {
child := current[*dimValue]
if child == nil {
child = make(map[string]interface{})
current[*dimValue] = child
}
current = child.(map[string]interface{})
}
}
}
// SetHLL sets hll struct to be the leaves of the nested map.
func (r AQLQueryResult) SetHLL(dimValues []*string, hll HLL) {
null := NULLString
var current map[string]interface{} = r
for i, dimValue := range dimValues {
if dimValue == nil {
dimValue = &null
}
if i == len(dimValues)-1 {
current[*dimValue] = hll
} else {
child := current[*dimValue]
if child == nil {
child = make(map[string]interface{})
current[*dimValue] = child
}
current = child.(map[string]interface{})
}
}
}
// ===== Time series result methods end =====
// ===== Non aggregate query result methods start =====
// Append appends one row
func (r AQLQueryResult) append(row []interface{}) {
if _, ok := r[MatrixDataKey]; !ok {
r[MatrixDataKey] = [][]interface{}{}
}
r[MatrixDataKey] = append(r[MatrixDataKey].([][]interface{}), row)
}
func (r AQLQueryResult) Append(dimValues []*string) {
values := make([]interface{}, len(dimValues))
for index, v := range dimValues {
if v == nil {
values[index] = NULLString
} else {
values[index] = *v
}
}
r.append(values)
}
// SetHeaders sets headers field for the results
func (r AQLQueryResult) SetHeaders(headers []string) {
r[HeadersKey] = headers
}
// ===== Non aggregate query result methods end =====