github.com/rohankumardubey/aresdb@v0.0.2-0.20190517170215-e54e3ca06b9c/query/common/aql_query_result.go (about)

     1  //  Copyright (c) 2017-2018 Uber Technologies, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package common
    16  
    17  const (
    18  	MatrixDataKey = "matrixData"
    19  	HeadersKey    = "headers"
    20  )
    21  
    22  // AQLQueryResult represents final result of one AQL query
    23  //
    24  // It has 2 possible formats:
    25  // Time series result format:
    26  // One dimension on each layer:
    27  //  - there is always an outermost time dimension. it stores the start time of
    28  //    the bucket/duration (in seconds since Epoch).
    29  //  - after the time dimension, there could be zero or more layers of additional
    30  //    dimensions (all values are represented as strings). a special "NULL" string
    31  ///   is used to represent NULL values.
    32  //  - there is always a single measure, and the measure type is either float64
    33  //    or nil (not *float64);
    34  //
    35  // Non aggregate query result format:
    36  //  - there will be a "headers" key, value will be a list of column names
    37  //  - there will be a "matrixData" key, value will be a 2d arary of values (row formated)
    38  //
    39  // user should use it as only 1 of the 2 formats consistently
    40  type AQLQueryResult map[string]interface{}
    41  
    42  // =====  Time series result methods start =====
    43  
    44  // Set measure value for dimensions
    45  func (r AQLQueryResult) Set(dimValues []*string, measureValue *float64) {
    46  	null := "NULL"
    47  	var current map[string]interface{} = r
    48  	for i, dimValue := range dimValues {
    49  		if dimValue == nil {
    50  			dimValue = &null
    51  		}
    52  
    53  		if i == len(dimValues)-1 {
    54  			if measureValue == nil {
    55  				current[*dimValue] = nil
    56  			} else {
    57  				current[*dimValue] = *measureValue
    58  			}
    59  		} else {
    60  			child := current[*dimValue]
    61  			if child == nil {
    62  				child = make(map[string]interface{})
    63  				current[*dimValue] = child
    64  			}
    65  			current = child.(map[string]interface{})
    66  		}
    67  	}
    68  }
    69  
    70  // SetHLL sets hll struct to be the leaves of the nested map.
    71  func (r AQLQueryResult) SetHLL(dimValues []*string, hll HLL) {
    72  	null := "NULL"
    73  	var current map[string]interface{} = r
    74  	for i, dimValue := range dimValues {
    75  		if dimValue == nil {
    76  			dimValue = &null
    77  		}
    78  
    79  		if i == len(dimValues)-1 {
    80  			current[*dimValue] = hll
    81  		} else {
    82  			child := current[*dimValue]
    83  			if child == nil {
    84  				child = make(map[string]interface{})
    85  				current[*dimValue] = child
    86  			}
    87  			current = child.(map[string]interface{})
    88  		}
    89  	}
    90  }
    91  
    92  // =====  Time series result methods end =====
    93  
    94  // =====  Non aggregate query result methods start =====
    95  
    96  // Append appends one row
    97  func (r AQLQueryResult) append(row []interface{}) {
    98  	if _, ok := r[MatrixDataKey]; !ok {
    99  		r[MatrixDataKey] = [][]interface{}{}
   100  	}
   101  
   102  	r[MatrixDataKey] = append(r[MatrixDataKey].([][]interface{}), row)
   103  }
   104  
   105  func (r AQLQueryResult) Append(dimValues []*string) {
   106  	values := make([]interface{}, len(dimValues))
   107  	for index, v := range dimValues {
   108  		if v == nil {
   109  			values[index] = "NULL"
   110  		} else {
   111  			values[index] = *v
   112  		}
   113  	}
   114  	r.append(values)
   115  }
   116  
   117  // SetHeaders sets headers field for the results
   118  func (r AQLQueryResult) SetHeaders(headers []string) {
   119  	r[HeadersKey] = headers
   120  }
   121  
   122  // =====  Non aggregate query result methods end =====