github.com/rohankumardubey/aresdb@v0.0.2-0.20190517170215-e54e3ca06b9c/query/aql_postprocessor_test.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 query 16 17 import ( 18 "github.com/onsi/ginkgo" 19 . "github.com/onsi/gomega" 20 memCom "github.com/uber/aresdb/memstore/common" 21 queryCom "github.com/uber/aresdb/query/common" 22 "github.com/uber/aresdb/query/expr" 23 "github.com/uber/aresdb/utils" 24 "time" 25 "unsafe" 26 ) 27 28 var _ = ginkgo.Describe("AQL postprocessor", func() { 29 ginkgo.It("works on empty result", func() { 30 ctx := &AQLQueryContext{} 31 Ω(ctx.Postprocess()).Should(Equal(queryCom.AQLQueryResult{})) 32 }) 33 34 ginkgo.It("works on one dimension and one row", func() { 35 ctx := &AQLQueryContext{ 36 Query: &AQLQuery{ 37 Dimensions: []Dimension{ 38 {Expr: ""}, 39 }, 40 }, 41 } 42 oopkContext := OOPKContext{ 43 Dimensions: []expr.Expr{ 44 &expr.VarRef{ 45 ExprType: expr.Unsigned, 46 DataType: memCom.Uint32, 47 }, 48 }, 49 Measure: &expr.NumberLiteral{ 50 ExprType: expr.Float, 51 }, 52 MeasureBytes: 4, 53 DimRowBytes: 5, 54 DimensionVectorIndex: []int{0}, 55 NumDimsPerDimWidth: queryCom.DimCountsPerDimWidth{0, 0, 1, 0, 0}, 56 ResultSize: 1, 57 dimensionVectorH: unsafe.Pointer(&[]uint8{12, 0, 0, 0, 1}[0]), 58 measureVectorH: unsafe.Pointer(&[]float32{3.2}[0]), 59 } 60 61 ctx.OOPK = oopkContext 62 63 Ω(ctx.Postprocess()).Should(Equal(queryCom.AQLQueryResult{ 64 "12": float64(float32(3.2)), 65 })) 66 }) 67 68 ginkgo.It("works on two dimensions and two rows", func() { 69 ctx := &AQLQueryContext{ 70 Query: &AQLQuery{ 71 Dimensions: []Dimension{ 72 {Expr: ""}, 73 {Expr: ""}, 74 }, 75 }, 76 } 77 oopkContext := OOPKContext{ 78 Dimensions: []expr.Expr{ 79 &expr.VarRef{ 80 ExprType: expr.Unsigned, 81 DataType: memCom.BigEnum, 82 EnumReverseDict: []string{"zero", "one", "two"}, 83 }, 84 &expr.NumberLiteral{ 85 ExprType: expr.Signed, 86 }, 87 }, 88 Measure: &expr.NumberLiteral{ 89 ExprType: expr.Float, 90 }, 91 MeasureBytes: 4, 92 DimRowBytes: 8, 93 NumDimsPerDimWidth: queryCom.DimCountsPerDimWidth{0, 0, 1, 1, 0}, 94 DimensionVectorIndex: []int{ 95 1, 96 0, 97 }, 98 ResultSize: 2, 99 dimensionVectorH: unsafe.Pointer(&[]uint8{12, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 1, 0, 1, 1}[0]), 100 measureVectorH: unsafe.Pointer(&[]float32{3.2, 6.4}[0]), 101 } 102 103 ctx.OOPK = oopkContext 104 Ω(ctx.Postprocess()).Should(Equal(queryCom.AQLQueryResult{ 105 "two": map[string]interface{}{ 106 "12": float64(float32(3.2)), 107 "NULL": float64(float32(6.4)), 108 }, 109 })) 110 }) 111 112 ginkgo.It("works on float dimension and nil measure", func() { 113 ctx := &AQLQueryContext{ 114 Query: &AQLQuery{ 115 Dimensions: []Dimension{ 116 {Expr: ""}, 117 }, 118 }, 119 } 120 oopkContext := OOPKContext{ 121 Dimensions: []expr.Expr{ 122 &expr.VarRef{ 123 ExprType: expr.Float, 124 DataType: memCom.Float32, 125 }, 126 }, 127 Measure: &expr.NumberLiteral{ 128 ExprType: expr.UnknownType, 129 }, 130 DimRowBytes: 5, 131 NumDimsPerDimWidth: queryCom.DimCountsPerDimWidth{0, 0, 1, 0, 0}, 132 DimensionVectorIndex: []int{ 133 0, 134 }, 135 ResultSize: 1, 136 dimensionVectorH: unsafe.Pointer(&[]uint8{0, 0, 0, 0, 0}[0]), 137 measureVectorH: unsafe.Pointer(&[]float32{3.2}[0]), 138 } 139 140 ctx.OOPK = oopkContext 141 *(*float32)(oopkContext.dimensionVectorH) = 3.2 142 *(*uint8)(utils.MemAccess(oopkContext.dimensionVectorH, 4)) = 1 143 144 Ω(ctx.Postprocess()).Should(Equal(queryCom.AQLQueryResult{ 145 "3.2": nil, 146 })) 147 }) 148 149 ginkgo.It("works for non agg queries", func() { 150 ctx := &AQLQueryContext{ 151 Query: &AQLQuery{ 152 Dimensions: []Dimension{ 153 {Expr: "someField"}, 154 }, 155 }, 156 isNonAggregationQuery: true, 157 } 158 oopkContext := OOPKContext{ 159 Dimensions: []expr.Expr{ 160 &expr.VarRef{ 161 ExprType: expr.Float, 162 DataType: memCom.Float32, 163 }, 164 }, 165 DimRowBytes: 5, 166 NumDimsPerDimWidth: queryCom.DimCountsPerDimWidth{0, 0, 1, 0, 0}, 167 DimensionVectorIndex: []int{ 168 0, 169 }, 170 ResultSize: 1, 171 dimensionVectorH: unsafe.Pointer(&[]uint8{0, 0, 0, 0, 0}[0]), 172 } 173 174 ctx.OOPK = oopkContext 175 *(*float32)(oopkContext.dimensionVectorH) = 3.2 176 *(*uint8)(utils.MemAccess(oopkContext.dimensionVectorH, 4)) = 1 177 178 Ω(ctx.Postprocess()).Should(Equal(queryCom.AQLQueryResult{ 179 "headers": []string{"someField"}, 180 "matrixData": [][]interface{}{{"3.2"}}, 181 })) 182 }) 183 184 ginkgo.It("time Unit formatting works", func() { 185 query := &AQLQuery{ 186 Dimensions: []Dimension{ 187 { 188 TimeBucketizer: "h", 189 }, 190 { 191 Expr: "", 192 }, 193 }, 194 } 195 ctx := &AQLQueryContext{ 196 Query: query, 197 } 198 oopkContext := OOPKContext{ 199 Dimensions: []expr.Expr{ 200 &expr.VarRef{ 201 ExprType: expr.Unsigned, 202 DataType: memCom.Uint32, 203 }, 204 &expr.NumberLiteral{ 205 ExprType: expr.Signed, 206 }, 207 }, 208 Measure: &expr.NumberLiteral{ 209 ExprType: expr.Float, 210 }, 211 MeasureBytes: 4, 212 DimRowBytes: 10, 213 NumDimsPerDimWidth: queryCom.DimCountsPerDimWidth{0, 0, 2, 0, 0}, 214 DimensionVectorIndex: []int{ 215 0, 216 1, 217 }, 218 ResultSize: 2, 219 dimensionVectorH: unsafe.Pointer(&[]uint8{190, 0, 0, 0, 250, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 1, 1, 1, 1}[0]), 220 measureVectorH: unsafe.Pointer(&[]float32{3.2, 6.4}[0]), 221 } 222 223 ctx.OOPK = oopkContext 224 Ω(ctx.Postprocess()).Should(Equal(queryCom.AQLQueryResult{ 225 "1970-01-01 00:00": map[string]interface{}{ 226 "2": 6.400000095367432, 227 }, 228 })) 229 230 ctx.Query.Dimensions[0].TimeBucketizer = "time of day" 231 Ω(ctx.Postprocess()).Should(Equal(queryCom.AQLQueryResult{ 232 "00:03": map[string]interface{}{ 233 "2": float64(float32(3.2)), 234 }, 235 "00:04": map[string]interface{}{ 236 "2": 6.400000095367432, 237 }, 238 })) 239 240 ctx.Query.Dimensions[0].TimeBucketizer = "hour of day" 241 Ω(ctx.Postprocess()).Should(Equal(queryCom.AQLQueryResult{ 242 "00:00": map[string]interface{}{ 243 "2": 6.400000095367432, 244 }, 245 })) 246 247 ctx.Query.Dimensions[0].TimeBucketizer = "hour of week" 248 Ω(ctx.Postprocess()).Should(Equal(queryCom.AQLQueryResult{ 249 "Monday 00:03": map[string]interface{}{ 250 "2": float64(float32(3.2)), 251 }, 252 "Monday 00:04": map[string]interface{}{ 253 "2": 6.400000095367432, 254 }, 255 })) 256 257 ctx.Query.Dimensions[0].TimeBucketizer = "minute" 258 Ω(ctx.Postprocess()).Should(Equal(queryCom.AQLQueryResult{ 259 "1970-01-01 00:03": map[string]interface{}{ 260 "2": float64(float32(3.2)), 261 }, 262 "1970-01-01 00:04": map[string]interface{}{ 263 "2": 6.400000095367432, 264 }, 265 })) 266 267 ctx.Query.Dimensions[0].TimeBucketizer = "hour" 268 Ω(ctx.Postprocess()).Should(Equal(queryCom.AQLQueryResult{ 269 "1970-01-01 00:00": map[string]interface{}{ 270 "2": 6.400000095367432, 271 }, 272 })) 273 274 ctx.Query.Dimensions[0].TimeBucketizer = "some invalid bucketizer" 275 Ω(ctx.Postprocess()).Should(Equal(queryCom.AQLQueryResult{ 276 "190": map[string]interface{}{ 277 "2": float64(float32(3.2)), 278 }, 279 "250": map[string]interface{}{ 280 "2": 6.400000095367432, 281 }, 282 })) 283 284 ctx.OOPK.dimensionVectorH = unsafe.Pointer(&[]uint8{1, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 1, 1, 1, 1}[0]) 285 ctx.Query.Dimensions[0].TimeBucketizer = "day of week" 286 Ω(ctx.Postprocess()).Should(Equal(queryCom.AQLQueryResult{ 287 "Tuesday": map[string]interface{}{ 288 "2": float64(float32(3.2)), 289 }, 290 "Wednesday": map[string]interface{}{ 291 "2": 6.400000095367432, 292 }, 293 })) 294 295 }) 296 297 ginkgo.It("time dimension remedy should work", func() { 298 query := &AQLQuery{ 299 Dimensions: []Dimension{ 300 { 301 Expr: "reqeust_at", 302 TimeBucketizer: "d", 303 TimeUnit: "second", 304 }, 305 { 306 Expr: "1", 307 }, 308 }, 309 TimeFilter: TimeFilter{ 310 Column: "request_at", 311 From: "-1d", 312 To: "0d", 313 }, 314 } 315 tzloc, _ := time.LoadLocation("Africa/Algiers") 316 ctx := &AQLQueryContext{ 317 Query: query, 318 fixedTimezone: time.UTC, 319 } 320 ctx1 := &AQLQueryContext{ 321 Query: query, 322 fixedTimezone: tzloc, 323 } 324 ctx.parseExprs() 325 Ω(ctx.Error).Should(BeNil()) 326 ctx1.parseExprs() 327 Ω(ctx1.Error).Should(BeNil()) 328 oopkContext := OOPKContext{ 329 Dimensions: []expr.Expr{ 330 &expr.VarRef{ 331 ExprType: expr.Unsigned, 332 DataType: memCom.Uint32, 333 }, 334 &expr.NumberLiteral{ 335 ExprType: expr.Signed, 336 }, 337 }, 338 Measure: &expr.NumberLiteral{ 339 ExprType: expr.Float, 340 }, 341 MeasureBytes: 4, 342 DimRowBytes: 10, 343 NumDimsPerDimWidth: queryCom.DimCountsPerDimWidth{0, 0, 2, 0, 0}, 344 DimensionVectorIndex: []int{ 345 0, 346 1, 347 }, 348 ResultSize: 2, 349 dimensionVectorH: unsafe.Pointer(&[]uint8{12, 100, 0, 0, 13, 100, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 1, 1, 1, 1}[0]), 350 measureVectorH: unsafe.Pointer(&[]float32{3.2, 6.4}[0]), 351 } 352 353 ctx.OOPK = oopkContext 354 Ω(ctx.Postprocess()).Should(Equal(queryCom.AQLQueryResult{ 355 "25612": map[string]interface{}{ 356 "2": float64(float32(3.2)), 357 }, 358 "25613": map[string]interface{}{ 359 "2": 6.400000095367432, 360 }, 361 })) 362 363 ctx1.OOPK = oopkContext 364 Ω(ctx1.Postprocess()).Should(Equal(queryCom.AQLQueryResult{ 365 "22012": map[string]interface{}{ 366 "2": float64(float32(3.2)), 367 }, 368 "22013": map[string]interface{}{ 369 "2": 6.400000095367432, 370 }, 371 })) 372 }) 373 374 ginkgo.It("readMeasure should work", func() { 375 // read an 8 bytes int64 376 measureVectorInt := [1]int64{1} 377 measureAST := &expr.NumberLiteral{ 378 ExprType: expr.Signed, 379 } 380 381 measureVal := readMeasure(unsafe.Pointer(&measureVectorInt[0]), measureAST, 8) 382 Ω(measureVal).ShouldNot(BeNil()) 383 Ω(*measureVal).Should(Equal(1.0)) 384 385 // read a 4 bytes float 386 measureVectorFloat := [2]float32{1.0, 0} 387 measureAST = &expr.NumberLiteral{ 388 ExprType: expr.Float, 389 } 390 measureVal = readMeasure(unsafe.Pointer(&measureVectorFloat[0]), measureAST, 4) 391 Ω(measureVal).ShouldNot(BeNil()) 392 Ω(*measureVal).Should(BeEquivalentTo(1.0)) 393 }) 394 })