github.com/rohankumardubey/aresdb@v0.0.2-0.20190517170215-e54e3ca06b9c/query/aql_processor_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 "unsafe" 19 20 "encoding/binary" 21 "encoding/json" 22 "math" 23 "strconv" 24 "sync" 25 "time" 26 27 "github.com/onsi/ginkgo" 28 . "github.com/onsi/gomega" 29 "github.com/stretchr/testify/mock" 30 "github.com/uber-go/tally" 31 "github.com/uber/aresdb/common" 32 "github.com/uber/aresdb/diskstore" 33 diskMocks "github.com/uber/aresdb/diskstore/mocks" 34 "github.com/uber/aresdb/memstore" 35 memCom "github.com/uber/aresdb/memstore/common" 36 memComMocks "github.com/uber/aresdb/memstore/common/mocks" 37 memMocks "github.com/uber/aresdb/memstore/mocks" 38 "github.com/uber/aresdb/memutils" 39 "github.com/uber/aresdb/metastore" 40 metaCom "github.com/uber/aresdb/metastore/common" 41 metaMocks "github.com/uber/aresdb/metastore/mocks" 42 queryCom "github.com/uber/aresdb/query/common" 43 "github.com/uber/aresdb/query/expr" 44 "github.com/uber/aresdb/utils" 45 ) 46 47 // readDeviceVPSlice reads a vector party from file and also translate it to device vp format: 48 // counts, nulls and values will be stored in a continuous memory space. 49 func readDeviceVPSlice(factory memstore.TestFactoryT, name string, stream unsafe.Pointer, 50 device int) (deviceVectorPartySlice, error) { 51 sourceVP, err := factory.ReadArchiveVectorParty(name, &sync.RWMutex{}) 52 if err != nil { 53 return deviceVectorPartySlice{}, err 54 } 55 56 hostVPSlice := sourceVP.GetHostVectorPartySlice(0, sourceVP.GetLength()) 57 deviceVPSlice := hostToDeviceColumn(hostVPSlice, device) 58 copyHostToDevice(hostVPSlice, deviceVPSlice, stream, device) 59 return deviceVPSlice, nil 60 } 61 62 var _ = ginkgo.Describe("aql_processor", func() { 63 var batch99, batch101, batch110, batch120, batch130 *memstore.Batch 64 var vs memstore.LiveStore 65 var archiveBatch0 *memstore.ArchiveBatch 66 var archiveBatch1 *memstore.ArchiveBatch 67 var memStore memstore.MemStore 68 var metaStore metastore.MetaStore 69 var diskStore diskstore.DiskStore 70 var hostMemoryManager memCom.HostMemoryManager 71 var shard *memstore.TableShard 72 table := "table1" 73 shardID := 0 74 75 testFactory := memstore.TestFactoryT{ 76 RootPath: "../testing/data", 77 FileSystem: utils.OSFileSystem{}, 78 } 79 80 ginkgo.BeforeEach(func() { 81 hostMemoryManager = new(memComMocks.HostMemoryManager) 82 hostMemoryManager.(*memComMocks.HostMemoryManager).On("ReportUnmanagedSpaceUsageChange", mock.Anything).Return() 83 memStore = new(memMocks.MemStore) 84 diskStore = new(diskMocks.DiskStore) 85 86 var err error 87 batch110, err = testFactory.ReadLiveBatch("archiving/batch-110") 88 Ω(err).Should(BeNil()) 89 batch101, err = testFactory.ReadLiveBatch("archiving/batch-101") 90 Ω(err).Should(BeNil()) 91 batch99, err = testFactory.ReadLiveBatch("archiving/batch-99") 92 Ω(err).Should(BeNil()) 93 batch120, err = testFactory.ReadLiveBatch("live/batch-120") 94 Ω(err).Should(BeNil()) 95 batch130, err = testFactory.ReadLiveBatch("live/batch-130") 96 Ω(err).Should(BeNil()) 97 tmpBatch, err := testFactory.ReadArchiveBatch("archiving/archiveBatch0") 98 tmpBatch1, err := testFactory.ReadArchiveBatch("archiving/archiveBatch1") 99 100 Ω(err).Should(BeNil()) 101 102 metaStore = new(metaMocks.MetaStore) 103 metaStore.(*metaMocks.MetaStore).On("GetArchiveBatchVersion", table, 0, mock.Anything, mock.Anything).Return(uint32(0), uint32(0), 0, nil) 104 105 diskStore = new(diskMocks.DiskStore) 106 diskStore.(*diskMocks.DiskStore).On( 107 "OpenVectorPartyFileForRead", table, mock.Anything, shardID, mock.Anything, mock.Anything, mock.Anything).Return(nil, nil) 108 109 shard = memstore.NewTableShard(&memstore.TableSchema{ 110 Schema: metaCom.Table{ 111 Name: table, 112 Config: metaCom.TableConfig{ 113 ArchivingDelayMinutes: 500, 114 ArchivingIntervalMinutes: 300, 115 }, 116 IsFactTable: true, 117 ArchivingSortColumns: []int{1, 2}, 118 Columns: []metaCom.Column{ 119 {Deleted: false, Name: "c0", Type: metaCom.Uint32}, 120 {Deleted: false, Name: "c1", Type: metaCom.Bool}, 121 {Deleted: false, Name: "c2", Type: metaCom.Float32}, 122 }, 123 }, 124 ColumnIDs: map[string]int{ 125 "c0": 0, 126 "c1": 1, 127 "c2": 2, 128 }, 129 ValueTypeByColumn: []memCom.DataType{memCom.Uint32, memCom.Bool, memCom.Float32}, 130 DefaultValues: []*memCom.DataValue{&memCom.NullDataValue, &memCom.NullDataValue, &memCom.NullDataValue}, 131 }, metaStore, diskStore, hostMemoryManager, shardID) 132 133 shardMap := map[int]*memstore.TableShard{ 134 shardID: shard, 135 } 136 137 archiveBatch0 = &memstore.ArchiveBatch{ 138 Version: 0, 139 Size: 5, 140 Shard: shard, 141 Batch: memstore.Batch{ 142 RWMutex: &sync.RWMutex{}, 143 Columns: tmpBatch.Columns, 144 }, 145 } 146 archiveBatch1 = &memstore.ArchiveBatch{ 147 Version: 0, 148 Size: 5, 149 Shard: shard, 150 Batch: memstore.Batch{ 151 RWMutex: &sync.RWMutex{}, 152 Columns: tmpBatch1.Columns, 153 }, 154 } 155 156 shard.ArchiveStore = &memstore.ArchiveStore{CurrentVersion: memstore.NewArchiveStoreVersion(100, shard)} 157 shard.ArchiveStore.CurrentVersion.Batches[0] = archiveBatch0 158 159 memStore.(*memMocks.MemStore).On("GetTableShard", "table1", 0).Run(func(args mock.Arguments) { 160 shard.Users.Add(1) 161 }).Return(shard, nil).Once() 162 163 memStore.(*memMocks.MemStore).On("RLock").Return() 164 memStore.(*memMocks.MemStore).On("RUnlock").Return() 165 memStore.(*memMocks.MemStore).On("GetSchemas").Return(map[string]*memstore.TableSchema{ 166 table: shard.Schema, 167 }) 168 169 vs = memstore.LiveStore{ 170 LastReadRecord: memstore.RecordID{BatchID: -101, Index: 3}, 171 Batches: map[int32]*memstore.LiveBatch{ 172 -110: { 173 Batch: memstore.Batch{ 174 RWMutex: &sync.RWMutex{}, 175 Columns: batch110.Columns, 176 }, 177 Capacity: 5, 178 }, 179 -101: { 180 Batch: memstore.Batch{ 181 RWMutex: &sync.RWMutex{}, 182 Columns: batch101.Columns, 183 }, 184 Capacity: 5, 185 }, 186 -99: { 187 Batch: memstore.Batch{ 188 RWMutex: &sync.RWMutex{}, 189 Columns: batch99.Columns, 190 }, 191 Capacity: 5, 192 }, 193 }, 194 PrimaryKey: memstore.NewPrimaryKey(16, true, 0, hostMemoryManager), 195 HostMemoryManager: hostMemoryManager, 196 } 197 198 shardMap[shardID].LiveStore = &vs 199 shardMap[shardID].ArchiveStore.CurrentVersion.ArchivingCutoff = 100 200 shardMap[shardID].ArchiveStore.CurrentVersion.Batches[0] = archiveBatch0 201 }) 202 203 ginkgo.AfterEach(func() { 204 batch110.SafeDestruct() 205 batch101.SafeDestruct() 206 batch99.SafeDestruct() 207 da := getDeviceAllocator() 208 Ω(da.(*memoryTrackingDeviceAllocatorImpl).memoryUsage[0]).Should(BeEquivalentTo(0)) 209 }) 210 211 ginkgo.It("prefilterSlice", func() { 212 vp1, err := testFactory.ReadArchiveVectorParty("sortedVP7", nil) 213 vp2, err := testFactory.ReadArchiveVectorParty("sortedVP6", nil) 214 vp3, err := testFactory.ReadArchiveVectorParty("sortedVP8", nil) 215 Ω(err).Should(BeNil()) 216 217 qc1 := AQLQueryContext{ 218 TableScanners: []*TableScanner{ 219 { 220 EqualityPrefilterValues: []uint32{1, 2}, 221 RangePrefilterBoundaries: [2]boundaryType{inclusiveBoundary, exclusiveBoundary}, 222 RangePrefilterValues: [2]uint32{1, 3}, 223 }, 224 }, 225 } 226 227 lowerBound, upperBound, vpSlice1 := qc1.prefilterSlice(vp1, 0, 0, 20) 228 Ω(vpSlice1.ValueStartIndex).Should(Equal(0)) 229 Ω(vpSlice1.ValueBytes).Should(Equal(64)) 230 Ω(vpSlice1.NullStartIndex).Should(Equal(0)) 231 Ω(vpSlice1.NullBytes).Should(Equal(64)) 232 Ω(vpSlice1.CountStartIndex).Should(Equal(0)) 233 Ω(vpSlice1.CountBytes).Should(Equal(64)) 234 235 lowerBound, upperBound, vpSlice2 := qc1.prefilterSlice(vp2, 1, lowerBound, upperBound) 236 Ω(vpSlice2.ValueStartIndex).Should(Equal(1)) 237 Ω(vpSlice2.ValueBytes).Should(Equal(64)) 238 Ω(vpSlice2.NullStartIndex).Should(Equal(1)) 239 Ω(vpSlice2.NullBytes).Should(Equal(64)) 240 Ω(vpSlice2.CountStartIndex).Should(Equal(1)) 241 Ω(vpSlice2.CountBytes).Should(Equal(64)) 242 243 lowerBound, upperBound, vpSlice3 := qc1.prefilterSlice(vp3, 2, lowerBound, upperBound) 244 245 Ω(vpSlice3.ValueStartIndex).Should(Equal(1)) 246 Ω(vpSlice3.ValueBytes).Should(Equal(64)) 247 Ω(vpSlice3.NullStartIndex).Should(Equal(1)) 248 Ω(vpSlice3.NullBytes).Should(Equal(64)) 249 Ω(vpSlice3.CountStartIndex).Should(Equal(1)) 250 Ω(vpSlice3.CountBytes).Should(Equal(64)) 251 252 Ω(lowerBound).Should(Equal(2)) 253 Ω(upperBound).Should(Equal(4)) 254 255 qc2 := AQLQueryContext{ 256 TableScanners: []*TableScanner{ 257 { 258 EqualityPrefilterValues: []uint32{1}, 259 RangePrefilterBoundaries: [2]boundaryType{noBoundary, inclusiveBoundary}, 260 RangePrefilterValues: [2]uint32{0, 1}, 261 }, 262 }, 263 } 264 265 lowerBound, upperBound, vpSlice1 = qc2.prefilterSlice(vp1, 0, 0, 20) 266 Ω(vpSlice1.ValueStartIndex).Should(Equal(0)) 267 Ω(vpSlice1.ValueBytes).Should(Equal(64)) 268 Ω(vpSlice1.NullStartIndex).Should(Equal(0)) 269 Ω(vpSlice1.NullBytes).Should(Equal(64)) 270 Ω(vpSlice1.CountStartIndex).Should(Equal(0)) 271 Ω(vpSlice1.CountBytes).Should(Equal(64)) 272 273 lowerBound, upperBound, vpSlice2 = qc2.prefilterSlice(vp2, 1, lowerBound, upperBound) 274 Ω(vpSlice2.ValueStartIndex).Should(Equal(0)) 275 Ω(vpSlice2.ValueBytes).Should(Equal(64)) 276 Ω(vpSlice2.NullStartIndex).Should(Equal(0)) 277 Ω(vpSlice2.NullBytes).Should(Equal(64)) 278 Ω(vpSlice2.CountStartIndex).Should(Equal(0)) 279 Ω(vpSlice2.CountBytes).Should(Equal(64)) 280 281 lowerBound, upperBound, vpSlice3 = qc2.prefilterSlice(vp3, 2, lowerBound, upperBound) 282 Ω(vpSlice3.ValueStartIndex).Should(Equal(0)) 283 Ω(vpSlice3.ValueBytes).Should(Equal(64)) 284 Ω(vpSlice3.NullStartIndex).Should(Equal(0)) 285 Ω(vpSlice3.NullBytes).Should(Equal(64)) 286 Ω(vpSlice3.CountStartIndex).Should(Equal(0)) 287 Ω(vpSlice3.CountBytes).Should(Equal(64)) 288 289 Ω(lowerBound).Should(Equal(0)) 290 Ω(upperBound).Should(Equal(2)) 291 292 qc3 := AQLQueryContext{ 293 TableScanners: []*TableScanner{ 294 { 295 EqualityPrefilterValues: []uint32{1}, 296 RangePrefilterBoundaries: [2]boundaryType{exclusiveBoundary, noBoundary}, 297 RangePrefilterValues: [2]uint32{1, 0}, 298 }, 299 }, 300 } 301 302 lowerBound, upperBound, vpSlice1 = qc3.prefilterSlice(vp1, 0, 0, 20) 303 Ω(vpSlice1.ValueStartIndex).Should(Equal(0)) 304 Ω(vpSlice1.ValueBytes).Should(Equal(64)) 305 Ω(vpSlice1.NullStartIndex).Should(Equal(0)) 306 Ω(vpSlice1.NullBytes).Should(Equal(64)) 307 Ω(vpSlice1.CountStartIndex).Should(Equal(0)) 308 Ω(vpSlice1.CountBytes).Should(Equal(64)) 309 310 lowerBound, upperBound, vpSlice2 = qc3.prefilterSlice(vp2, 1, lowerBound, upperBound) 311 Ω(vpSlice2.ValueStartIndex).Should(Equal(1)) 312 Ω(vpSlice2.ValueBytes).Should(Equal(64)) 313 Ω(vpSlice2.NullStartIndex).Should(Equal(1)) 314 Ω(vpSlice2.NullBytes).Should(Equal(64)) 315 Ω(vpSlice2.CountStartIndex).Should(Equal(1)) 316 Ω(vpSlice2.CountBytes).Should(Equal(64)) 317 318 lowerBound, upperBound, vpSlice3 = qc3.prefilterSlice(vp3, 2, lowerBound, upperBound) 319 Ω(vpSlice3.ValueStartIndex).Should(Equal(1)) 320 Ω(vpSlice3.ValueBytes).Should(Equal(64)) 321 Ω(vpSlice3.NullStartIndex).Should(Equal(1)) 322 Ω(vpSlice3.NullBytes).Should(Equal(64)) 323 Ω(vpSlice3.CountStartIndex).Should(Equal(1)) 324 Ω(vpSlice3.CountBytes).Should(Equal(64)) 325 326 Ω(lowerBound).Should(Equal(2)) 327 Ω(upperBound).Should(Equal(5)) 328 }) 329 330 ginkgo.It("makeForeignColumnVectorInput", func() { 331 values := [64]byte{} 332 nulls := [64]byte{} 333 334 table := foreignTable{ 335 batches: [][]deviceVectorPartySlice{ 336 { 337 { 338 values: devicePointer{pointer: unsafe.Pointer(&values[0])}, 339 nulls: devicePointer{pointer: unsafe.Pointer(&nulls[0])}, 340 length: 10, 341 valueType: memCom.Uint16, 342 }, 343 { 344 values: devicePointer{pointer: unsafe.Pointer(&values[0])}, 345 nulls: devicePointer{pointer: unsafe.Pointer(&nulls[0])}, 346 length: 10, 347 valueType: memCom.Uint8, 348 }, 349 }, 350 { 351 { 352 values: devicePointer{pointer: unsafe.Pointer(&values[0])}, 353 nulls: devicePointer{pointer: unsafe.Pointer(&nulls[0])}, 354 length: 10, 355 valueType: memCom.Uint16, 356 }, 357 { 358 values: devicePointer{pointer: unsafe.Pointer(&values[0])}, 359 nulls: devicePointer{pointer: unsafe.Pointer(&nulls[0])}, 360 length: 10, 361 valueType: memCom.Uint8, 362 }, 363 }, 364 }, 365 } 366 367 inputVector := makeForeignColumnInput(0, unsafe.Pointer(uintptr(0)), table, nil, 0) 368 Ω(inputVector.Type).Should(Equal(uint32(3))) 369 }) 370 371 ginkgo.It("makeVectorPartySliceInput", func() { 372 values := [64]byte{} 373 nulls := [64]byte{} 374 counts := [64]byte{} 375 376 column := deviceVectorPartySlice{ 377 values: devicePointer{pointer: unsafe.Pointer(&values[0])}, 378 nulls: devicePointer{pointer: unsafe.Pointer(&nulls[0])}, 379 counts: devicePointer{pointer: unsafe.Pointer(&counts[0])}, 380 length: 10, 381 valueType: memCom.Uint16, 382 valueStartIndex: 1, 383 nullStartIndex: 0, 384 countStartIndex: 1, 385 } 386 inputVector := makeVectorPartySliceInput(column) 387 // uint32(0) corresponds to VectorPartySlice in C.enum_InputVectorType 388 Ω(inputVector.Type).Should(Equal(uint32(0))) 389 }) 390 391 ginkgo.It("makeConstantInput", func() { 392 inputVector := makeConstantInput(float64(1.0), false) 393 // uint32(2) corresponds to ConstantInput in C.enum_InputVectorType 394 Ω(inputVector.Type).Should(Equal(uint32(2))) 395 396 inputVector = makeConstantInput(int(1), false) 397 Ω(inputVector.Type).Should(Equal(uint32(2))) 398 399 v := &expr.GeopointLiteral{Val: [2]float32{1.1, 2.2}} 400 inputVector = makeConstantInput(v, false) 401 Ω(inputVector.Type).Should(Equal(uint32(2))) 402 }) 403 404 ginkgo.It("makeScratchSpaceInput", func() { 405 values := [64]byte{} 406 nulls := [64]byte{} 407 inputVector := makeScratchSpaceInput(unsafe.Pointer(&values[0]), unsafe.Pointer(&nulls[0]), uint32(1)) 408 // uint32(1) corresponds to ScratchSpaceInput in C.enum_InputVectorType 409 Ω(inputVector.Type).Should(Equal(uint32(1))) 410 }) 411 412 ginkgo.It("makeScratchSpaceOutput", func() { 413 values := [64]byte{} 414 nulls := [64]byte{} 415 outputVector := makeScratchSpaceOutput(unsafe.Pointer(&values[0]), unsafe.Pointer(&nulls[0]), uint32(0)) 416 // uint32(0) corresponds to ScratchSpaceOutput in C.enum_OutputVectorType 417 Ω(outputVector.Type).Should(Equal(uint32(0))) 418 }) 419 420 ginkgo.It("makeMeasureVectorOutput", func() { 421 measureValues := [64]byte{} 422 outputVector := makeMeasureVectorOutput(unsafe.Pointer(&measureValues[0]), uint32(6), uint32(0)) 423 // uint32(0) corresponds to ScratchSpaceOutput in C.enum_OutputVectorType 424 Ω(outputVector.Type).Should(Equal(uint32(1))) 425 }) 426 427 ginkgo.It("makeDimensionVectorOutput", func() { 428 dimValues := [64]byte{} 429 outputVector := makeDimensionVectorOutput(unsafe.Pointer(&dimValues[0]), 0, 4, uint32(0)) 430 // uint32(0) corresponds to ScratchSpaceOutput in C.enum_OutputVectorType 431 Ω(outputVector.Type).Should(Equal(uint32(2))) 432 }) 433 434 ginkgo.It("evaluateFilterExpression", func() { 435 ctx := oopkBatchContext{} 436 defer ctx.cleanupDeviceResultBuffers() 437 defer ctx.cleanupBeforeAggregation() 438 defer ctx.swapResultBufferForNextBatch() 439 var stream unsafe.Pointer 440 vp0, err := readDeviceVPSlice(testFactory, "sortedVP8", stream, ctx.device) 441 Ω(err).Should(BeNil()) 442 vp1, err := readDeviceVPSlice(testFactory, "sortedVP7", stream, ctx.device) 443 Ω(err).Should(BeNil()) 444 vp2, err := readDeviceVPSlice(testFactory, "sortedVP6", stream, ctx.device) 445 Ω(err).Should(BeNil()) 446 columns := []deviceVectorPartySlice{ 447 vp0, 448 vp1, 449 vp2, 450 } 451 452 tableScanners := []*TableScanner{ 453 { 454 ColumnsByIDs: map[int]int{ 455 1: 1, 456 2: 2, 457 }, 458 }, 459 } 460 foreignTables := make([]*foreignTable, 0) 461 462 ctx.prepareForFiltering(columns, 0, 0, stream) 463 Ω(ctx.size).Should(Equal(6)) 464 initIndexVector(ctx.indexVectorD.getPointer(), 0, ctx.size, stream, 0) 465 466 // expr: -vp1 == -2 || vp2 >= 2 467 468 // id| vp0 | vp1 | vp2 | res | 469 // --------------------------- 470 // 0 | 1 0 | 1 0 | 1 0 | | 471 // 1 | 1 2 | | 2 2 | y | 472 // 2 | 2 3 | | | y | 473 // 3 | 3 4 | | | y | 474 // 4 | 2 5 | 2 5 | 1 5 | y | 475 // 5 | 2 10| | 2 10| y | 476 477 exp := &expr.BinaryExpr{ 478 Op: expr.OR, 479 LHS: &expr.BinaryExpr{ 480 Op: expr.EQ, 481 LHS: &expr.UnaryExpr{ 482 Op: expr.UNARY_MINUS, 483 Expr: &expr.VarRef{ 484 Val: "vp1", 485 ColumnID: 1, 486 }, 487 }, 488 RHS: &expr.NumberLiteral{ 489 Val: 0, 490 Int: -2, 491 ExprType: expr.Signed, 492 }, 493 }, 494 RHS: &expr.BinaryExpr{ 495 Op: expr.GTE, 496 LHS: &expr.VarRef{ 497 Val: "vp2", 498 ColumnID: 2, 499 }, 500 RHS: &expr.NumberLiteral{ 501 Val: 0, 502 Int: 2, 503 ExprType: expr.Unsigned, 504 }, 505 }, 506 } 507 508 ctx.processExpression(exp, nil, tableScanners, foreignTables, stream, 0, ctx.filterAction) 509 Ω(ctx.size).Should(Equal(5)) 510 ctx.cleanupBeforeAggregation() 511 ctx.swapResultBufferForNextBatch() 512 513 vp0, err = readDeviceVPSlice(testFactory, "sortedVP8", stream, ctx.device) 514 Ω(err).Should(BeNil()) 515 vp1, err = readDeviceVPSlice(testFactory, "sortedVP7", stream, ctx.device) 516 Ω(err).Should(BeNil()) 517 vp2, err = readDeviceVPSlice(testFactory, "sortedVP6", stream, ctx.device) 518 Ω(err).Should(BeNil()) 519 columns = []deviceVectorPartySlice{ 520 vp0, 521 vp1, 522 vp2, 523 } 524 525 // expr: vp2 / 2 == 0 526 exp = &expr.BinaryExpr{ 527 Op: expr.EQ, 528 LHS: &expr.BinaryExpr{ 529 Op: expr.DIV, 530 LHS: &expr.VarRef{ 531 Val: "vp2", 532 ColumnID: 2, 533 }, 534 RHS: &expr.NumberLiteral{ 535 Val: 2, 536 Int: 2, 537 Expr: "2", 538 ExprType: expr.Signed, 539 }, 540 }, 541 RHS: &expr.NumberLiteral{ 542 Val: 0, 543 Int: 0, 544 Expr: "0", 545 ExprType: expr.Signed, 546 }, 547 } 548 ctx.prepareForFiltering(columns, 0, 0, stream) 549 initIndexVector(ctx.indexVectorD.getPointer(), 0, ctx.size, stream, 0) 550 ctx.processExpression(exp, nil, tableScanners, foreignTables, stream, 0, ctx.filterAction) 551 Ω(ctx.size).Should(Equal(2)) 552 Ω(*(*uint32)(utils.MemAccess(ctx.indexVectorD.getPointer(), 0))).Should(Equal(uint32(0))) 553 Ω(*(*uint32)(utils.MemAccess(ctx.indexVectorD.getPointer(), 4))).Should(Equal(uint32(4))) 554 ctx.cleanupBeforeAggregation() 555 ctx.swapResultBufferForNextBatch() 556 }) 557 558 ginkgo.It("evaluateVarRefDimensionExpression", func() { 559 var stream unsafe.Pointer 560 ctx := oopkBatchContext{} 561 vpSlice0, err := readDeviceVPSlice(testFactory, "sortedVP8", stream, ctx.device) 562 Ω(err).Should(BeNil()) 563 vpSlice1, err := readDeviceVPSlice(testFactory, "sortedVP7", stream, ctx.device) 564 Ω(err).Should(BeNil()) 565 vpSlice2, err := readDeviceVPSlice(testFactory, "sortedVP6", stream, ctx.device) 566 Ω(err).Should(BeNil()) 567 columns := []deviceVectorPartySlice{ 568 vpSlice0, 569 vpSlice1, 570 vpSlice2, 571 } 572 tableScanners := []*TableScanner{ 573 { 574 ColumnsByIDs: map[int]int{ 575 1: 1, 576 2: 2, 577 }, 578 }, 579 } 580 581 foreignTables := make([]*foreignTable, 0) 582 oopkContext := OOPKContext{ 583 // only one 2 byte dimension 584 NumDimsPerDimWidth: queryCom.DimCountsPerDimWidth{0, 0, 0, 1, 0}, 585 // 2 bytes + 1 validity byte 586 DimRowBytes: 3, 587 } 588 589 // test boolean dimension value 590 ctx.prepareForFiltering(columns, 0, 0, stream) 591 initIndexVector(ctx.indexVectorD.getPointer(), 0, ctx.size, stream, 0) 592 ctx.prepareForDimAndMeasureEval(oopkContext.DimRowBytes, 4, oopkContext.NumDimsPerDimWidth, false, stream) 593 valueOffset, nullOffset := queryCom.GetDimensionStartOffsets(oopkContext.NumDimsPerDimWidth, 0, ctx.resultCapacity) 594 dimensionExprRootAction := ctx.makeWriteToDimensionVectorAction(valueOffset, nullOffset, 0) 595 // vp2 596 exp := &expr.VarRef{ 597 Val: "vp2", 598 ExprType: expr.Unsigned, 599 TableID: 0, 600 ColumnID: 2, 601 DataType: memCom.Uint16, 602 } 603 ctx.processExpression(exp, nil, tableScanners, foreignTables, stream, 0, dimensionExprRootAction) 604 Ω(*(*[18]uint8)(ctx.dimensionVectorD[0].getPointer())).Should(Equal([18]uint8{1, 0, 2, 0, 2, 0, 2, 0, 1, 0, 2, 0, 1, 1, 1, 1, 1, 1})) 605 ctx.cleanupBeforeAggregation() 606 ctx.swapResultBufferForNextBatch() 607 ctx.cleanupDeviceResultBuffers() 608 }) 609 610 ginkgo.It("evaluateBooleanDimensionExpression", func() { 611 var stream unsafe.Pointer 612 ctx := oopkBatchContext{} 613 vpSlice0, err := readDeviceVPSlice(testFactory, "sortedVP8", stream, ctx.device) 614 Ω(err).Should(BeNil()) 615 vpSlice1, err := readDeviceVPSlice(testFactory, "sortedVP7", stream, ctx.device) 616 Ω(err).Should(BeNil()) 617 vpSlice2, err := readDeviceVPSlice(testFactory, "sortedVP6", stream, ctx.device) 618 Ω(err).Should(BeNil()) 619 620 columns := []deviceVectorPartySlice{ 621 vpSlice0, 622 vpSlice1, 623 vpSlice2, 624 } 625 tableScanners := []*TableScanner{ 626 { 627 ColumnsByIDs: map[int]int{ 628 1: 1, 629 2: 2, 630 }, 631 }, 632 } 633 foreignTables := make([]*foreignTable, 0) 634 oopkContext := OOPKContext{ 635 NumDimsPerDimWidth: queryCom.DimCountsPerDimWidth{0, 0, 0, 0, 1}, 636 // test boolean dimension value 637 // 1 byte + 1 validity byte 638 DimRowBytes: 2, 639 } 640 641 ctx.prepareForFiltering(columns, 0, 0, stream) 642 initIndexVector(ctx.indexVectorD.getPointer(), 0, ctx.size, stream, 0) 643 ctx.prepareForDimAndMeasureEval(oopkContext.DimRowBytes, 4, oopkContext.NumDimsPerDimWidth, false, stream) 644 valueOffset, nullOffset := queryCom.GetDimensionStartOffsets(oopkContext.NumDimsPerDimWidth, 0, ctx.resultCapacity) 645 dimensionExprRootAction := ctx.makeWriteToDimensionVectorAction(valueOffset, nullOffset, 0) 646 // vp2 == 2 647 exp := &expr.BinaryExpr{ 648 Op: expr.EQ, 649 LHS: &expr.VarRef{ 650 Val: "vp2", 651 ColumnID: 2, 652 }, 653 RHS: &expr.NumberLiteral{ 654 Val: 2, 655 Int: 2, 656 Expr: "2", 657 ExprType: expr.Signed, 658 }, 659 ExprType: expr.Boolean, 660 } 661 ctx.processExpression(exp, nil, tableScanners, foreignTables, stream, 0, dimensionExprRootAction) 662 Ω(*(*[12]uint8)(ctx.dimensionVectorD[0].getPointer())).Should(Equal([12]uint8{0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1})) 663 ctx.cleanupBeforeAggregation() 664 ctx.swapResultBufferForNextBatch() 665 ctx.cleanupDeviceResultBuffers() 666 }) 667 668 ginkgo.It("evaluateDimensionExpression", func() { 669 ctx := oopkBatchContext{} 670 var stream unsafe.Pointer 671 vpSlice0, err := readDeviceVPSlice(testFactory, "sortedVP8", stream, ctx.device) 672 Ω(err).Should(BeNil()) 673 vpSlice1, err := readDeviceVPSlice(testFactory, "sortedVP7", stream, ctx.device) 674 Ω(err).Should(BeNil()) 675 vpSlice2, err := readDeviceVPSlice(testFactory, "sortedVP6", stream, ctx.device) 676 Ω(err).Should(BeNil()) 677 678 columns := []deviceVectorPartySlice{ 679 vpSlice0, 680 vpSlice1, 681 vpSlice2, 682 } 683 tableScanners := []*TableScanner{ 684 { 685 ColumnsByIDs: map[int]int{ 686 1: 1, 687 2: 2, 688 }, 689 }, 690 } 691 foreignTables := make([]*foreignTable, 0) 692 oopkContext := OOPKContext{ 693 NumDimsPerDimWidth: queryCom.DimCountsPerDimWidth{0, 0, 1, 0, 0}, 694 DimRowBytes: 5, 695 } 696 697 // id|vp0|vp1|vp2| 698 // --------------------- 699 // 0 | 1 | 1 | 1 | 700 // 1 | 1 | 1 | 2 | 701 // 2 | 2 | 1 | 2 | 702 // 3 | 3 | 1 | 2 | 703 // 4 | 2 | 2 | 1 | 704 // 5 | 2 | 2 | 2 | 705 706 // vp2 / 2 707 exp := &expr.BinaryExpr{ 708 Op: expr.DIV, 709 LHS: &expr.VarRef{ 710 Val: "vp2", 711 ColumnID: 2, 712 }, 713 RHS: &expr.NumberLiteral{ 714 Val: 2, 715 Int: 2, 716 Expr: "2", 717 ExprType: expr.Signed, 718 }, 719 ExprType: expr.Signed, 720 } 721 722 ctx.prepareForFiltering(columns, 0, 0, stream) 723 initIndexVector(ctx.indexVectorD.getPointer(), 0, ctx.size, stream, 0) 724 ctx.prepareForDimAndMeasureEval(oopkContext.DimRowBytes, 4, oopkContext.NumDimsPerDimWidth, false, stream) 725 valueOffset, nullOffset := queryCom.GetDimensionStartOffsets(oopkContext.NumDimsPerDimWidth, 0, ctx.resultCapacity) 726 dimensionExprRootAction := ctx.makeWriteToDimensionVectorAction(valueOffset, nullOffset, 0) 727 ctx.processExpression(exp, nil, tableScanners, foreignTables, stream, 0, dimensionExprRootAction) 728 Ω(*(*[30]uint8)(ctx.dimensionVectorD[0].getPointer())).Should(Equal([30]uint8{0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1})) 729 ctx.cleanupBeforeAggregation() 730 ctx.swapResultBufferForNextBatch() 731 ctx.cleanupDeviceResultBuffers() 732 733 }) 734 735 ginkgo.It("evaluateMeasureExpression", func() { 736 ctx := oopkBatchContext{} 737 var stream unsafe.Pointer 738 vpSlice0, err := readDeviceVPSlice(testFactory, "sortedVP8", stream, ctx.device) 739 Ω(err).Should(BeNil()) 740 vpSlice1, err := readDeviceVPSlice(testFactory, "sortedVP7", stream, ctx.device) 741 Ω(err).Should(BeNil()) 742 vpSlice2, err := readDeviceVPSlice(testFactory, "sortedVP6", stream, ctx.device) 743 Ω(err).Should(BeNil()) 744 745 columns := []deviceVectorPartySlice{ 746 vpSlice0, 747 vpSlice1, 748 vpSlice2, 749 } 750 751 tableScanners := []*TableScanner{ 752 { 753 ColumnsByIDs: map[int]int{ 754 1: 1, 755 2: 2, 756 }, 757 }, 758 } 759 foreignTables := make([]*foreignTable, 0) 760 761 // id|cnt|vp0|vp1|vp2| 762 // --------------------- 763 // 0 | 2 | 1 | 1 | 1 | 764 // 1 | 1 | 1 | 1 | 2 | 765 // 2 | 1 | 2 | 1 | 2 | 766 // 3 | 1 | 3 | 1 | 2 | 767 // 4 | 5 | 2 | 2 | 1 | 768 // 5 |10 | 2 | 2 | 2 | 769 770 // vp2 / 2 771 exp := &expr.BinaryExpr{ 772 Op: expr.DIV, 773 LHS: &expr.VarRef{ 774 Val: "vp2", 775 ColumnID: 2, 776 }, 777 RHS: &expr.NumberLiteral{ 778 Val: 2, 779 Int: 2, 780 Expr: "2", 781 ExprType: expr.Signed, 782 }, 783 } 784 785 dimRowBytes := 8 786 ctx.prepareForFiltering(columns, 0, 0, stream) 787 initIndexVector(ctx.indexVectorD.getPointer(), 0, ctx.size, stream, 0) 788 789 ctx.prepareForDimAndMeasureEval(dimRowBytes, 4, queryCom.DimCountsPerDimWidth{}, false, stream) 790 measureExprRootAction := ctx.makeWriteToMeasureVectorAction(uint32(1), 4) 791 ctx.processExpression(exp, nil, tableScanners, foreignTables, stream, 0, measureExprRootAction) 792 793 Ω(*(*uint32)(ctx.measureVectorD[0].getPointer())).Should(Equal(uint32(0))) 794 Ω(*(*uint32)(utils.MemAccess(ctx.measureVectorD[0].getPointer(), 4))).Should(Equal(uint32(1))) 795 Ω(*(*uint32)(utils.MemAccess(ctx.measureVectorD[0].getPointer(), 8))).Should(Equal(uint32(1))) 796 Ω(*(*uint32)(utils.MemAccess(ctx.measureVectorD[0].getPointer(), 12))).Should(Equal(uint32(1))) 797 Ω(*(*uint32)(utils.MemAccess(ctx.measureVectorD[0].getPointer(), 16))).Should(Equal(uint32(0))) 798 Ω(*(*uint32)(utils.MemAccess(ctx.measureVectorD[0].getPointer(), 20))).Should(Equal(uint32(10))) 799 ctx.cleanupBeforeAggregation() 800 ctx.swapResultBufferForNextBatch() 801 ctx.cleanupDeviceResultBuffers() 802 }) 803 804 ginkgo.It("sort", func() { 805 var stream unsafe.Pointer 806 // 3 total elements 807 dimensionVectorH := [9]uint8{2, 0, 1, 0, 2, 0, 1, 1, 1} 808 dimensionVectorD := deviceAllocate(3*3, 0) 809 memutils.AsyncCopyHostToDevice(dimensionVectorD.getPointer(), unsafe.Pointer(&dimensionVectorH), 3*3, stream, 0) 810 811 hashVectorD := deviceAllocate(8*3, 0) 812 dimIndexVectorH := [3]uint32{} 813 dimIndexVectorD := deviceAllocate(4*3, 0) 814 initIndexVector(dimIndexVectorD.getPointer(), 0, 3, stream, 0) 815 816 measureVectorH := [3]uint32{22, 11, 22} 817 measureVectorD := deviceAllocate(4*3, 0) 818 memutils.AsyncCopyHostToDevice(measureVectorD.getPointer(), unsafe.Pointer(&measureVectorH), 4*3, stream, 0) 819 820 numDims := queryCom.DimCountsPerDimWidth{0, 0, 0, 1, 0} 821 batchCtx := oopkBatchContext{ 822 dimensionVectorD: [2]devicePointer{dimensionVectorD, nullDevicePointer}, 823 hashVectorD: [2]devicePointer{hashVectorD, nullDevicePointer}, 824 dimIndexVectorD: [2]devicePointer{dimIndexVectorD, nullDevicePointer}, 825 measureVectorD: [2]devicePointer{measureVectorD, nullDevicePointer}, 826 size: 3, 827 resultSize: 0, 828 resultCapacity: 3, 829 } 830 831 batchCtx.sortByKey(numDims, stream, 0) 832 memutils.AsyncCopyDeviceToHost(unsafe.Pointer(&measureVectorH), measureVectorD.getPointer(), 12, stream, 0) 833 memutils.AsyncCopyDeviceToHost(unsafe.Pointer(&dimIndexVectorH), dimIndexVectorD.getPointer(), 12, stream, 0) 834 835 Ω(dimIndexVectorH).Should(Or(Equal([3]uint32{0, 2, 1}), Equal([3]uint32{1, 0, 2}), Equal([3]uint32{1, 2, 0}), Equal([3]uint32{2, 0, 1}))) 836 837 deviceFreeAndSetNil(&dimensionVectorD) 838 deviceFreeAndSetNil(&dimIndexVectorD) 839 deviceFreeAndSetNil(&hashVectorD) 840 deviceFreeAndSetNil(&measureVectorD) 841 }) 842 843 ginkgo.It("reduce", func() { 844 // one 4 byte dim 845 numDims := queryCom.DimCountsPerDimWidth{0, 0, 1, 0, 0} 846 var stream unsafe.Pointer 847 848 dimensionInputVector := [5]uint32{1, 1, 1, 2, 0x01010101} 849 hashInputVector := [4]uint64{1, 1, 1, 2} 850 dimIndexInputVector := [4]uint32{0, 1, 2, 3} 851 measureInputVector := [4]uint32{1, 2, 3, 4} 852 853 var dimensionOutputVector [5]uint32 854 var hashOutputVector [4]uint64 855 var dimIndexOutputVector [4]uint32 856 var measureOutputVector [4]uint32 857 858 batchCtx := oopkBatchContext{ 859 dimensionVectorD: [2]devicePointer{{pointer: unsafe.Pointer(&dimensionInputVector)}, {pointer: unsafe.Pointer(&dimensionOutputVector)}}, 860 hashVectorD: [2]devicePointer{{pointer: unsafe.Pointer(&hashInputVector)}, {pointer: unsafe.Pointer(&hashOutputVector)}}, 861 dimIndexVectorD: [2]devicePointer{{pointer: unsafe.Pointer(&dimIndexInputVector)}, {pointer: unsafe.Pointer(&dimIndexOutputVector)}}, 862 measureVectorD: [2]devicePointer{{pointer: unsafe.Pointer(&measureInputVector)}, {pointer: unsafe.Pointer(&measureOutputVector)}}, 863 size: 4, 864 resultSize: 0, 865 resultCapacity: 4, 866 } 867 868 // 1 is AGGR_SUM_UNSIGNED 869 batchCtx.reduceByKey(numDims, 4, uint32(1), stream, 0) 870 Ω(dimensionOutputVector).Should(Equal([5]uint32{1, 2, 0, 0, 0x0101})) 871 Ω(measureOutputVector).Should(Equal([4]uint32{6, 4, 0, 0})) 872 }) 873 874 ginkgo.It("estimateScratchSpaceMemUsage should work", func() { 875 expression, _ := expr.ParseExpr(`a`) 876 currentMemUsage, maxMemUsage := estimateScratchSpaceMemUsage(expression, 100, true) 877 Ω(currentMemUsage).Should(Equal(0)) 878 Ω(maxMemUsage).Should(Equal(0)) 879 880 currentMemUsage, maxMemUsage = estimateScratchSpaceMemUsage(expression, 100, false) 881 Ω(currentMemUsage).Should(Equal(0)) 882 Ω(maxMemUsage).Should(Equal(0)) 883 884 expression, _ = expr.ParseExpr(`a + b`) 885 currentMemUsage, maxMemUsage = estimateScratchSpaceMemUsage(expression, 100, true) 886 Ω(currentMemUsage).Should(Equal(0)) 887 Ω(maxMemUsage).Should(Equal(0)) 888 889 currentMemUsage, maxMemUsage = estimateScratchSpaceMemUsage(expression, 100, false) 890 Ω(currentMemUsage).Should(Equal(500)) 891 Ω(maxMemUsage).Should(Equal(500)) 892 893 expression, _ = expr.ParseExpr(`(a+b) + (c+d)`) 894 currentMemUsage, maxMemUsage = estimateScratchSpaceMemUsage(expression, 100, true) 895 Ω(currentMemUsage).Should(Equal(0)) 896 Ω(maxMemUsage).Should(Equal(1000)) 897 898 currentMemUsage, maxMemUsage = estimateScratchSpaceMemUsage(expression, 100, false) 899 Ω(currentMemUsage).Should(Equal(500)) 900 Ω(maxMemUsage).Should(Equal(1500)) 901 902 expression, _ = expr.ParseExpr(`((a1+b1) + (c1+d1)) * ((a2+b2) + (c2+d2))`) 903 currentMemUsage, maxMemUsage = estimateScratchSpaceMemUsage(expression, 100, true) 904 Ω(currentMemUsage).Should(Equal(0)) 905 Ω(maxMemUsage).Should(Equal(1500)) 906 907 currentMemUsage, maxMemUsage = estimateScratchSpaceMemUsage(expression, 100, false) 908 Ω(currentMemUsage).Should(Equal(500)) 909 Ω(maxMemUsage).Should(Equal(1500)) 910 }) 911 912 ginkgo.It("copy dimension vector should work", func() { 913 dvDevice := [40]uint8{2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 0, 0, 0, 0, 2, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0} 914 dvHostExpected := [20]uint8{2, 0, 0, 0, 1, 0, 0, 0, 2, 0, 1, 0, 2, 1, 1, 1, 1, 1, 1, 1} 915 ctx := oopkBatchContext{ 916 dimensionVectorD: [2]devicePointer{{pointer: unsafe.Pointer(&dvDevice[0])}, nullDevicePointer}, 917 resultSize: 2, 918 resultCapacity: 4, 919 } 920 dvHost := [20]uint8{} 921 dimensionVectorHost := unsafe.Pointer(&dvHost[0]) 922 numDims := queryCom.DimCountsPerDimWidth{0, 0, 1, 1, 1} 923 var stream unsafe.Pointer 924 asyncCopyDimensionVector(dimensionVectorHost, ctx.dimensionVectorD[0].getPointer(), ctx.resultSize, 0, 925 numDims, ctx.resultSize, ctx.resultCapacity, memutils.AsyncCopyDeviceToHost, stream, 0) 926 Ω(dvHost).Should(Equal(dvHostExpected)) 927 }) 928 929 ginkgo.It("copy dimension vector with offset should work", func() { 930 dvDevice := [40]uint8{2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 0, 0, 0, 0, 2, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0} 931 dvHostExpected := [40]uint8{0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 0, 0, 0, 2, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0} 932 ctx := oopkBatchContext{ 933 dimensionVectorD: [2]devicePointer{{pointer: unsafe.Pointer(&dvDevice[0])}, nullDevicePointer}, 934 resultSize: 2, 935 resultCapacity: 4, 936 } 937 dvHost := [40]uint8{} 938 dimensionVectorHost := unsafe.Pointer(&dvHost[0]) 939 numDims := queryCom.DimCountsPerDimWidth{0, 0, 1, 1, 1} 940 var stream unsafe.Pointer 941 asyncCopyDimensionVector(dimensionVectorHost, ctx.dimensionVectorD[0].getPointer(), ctx.resultSize, 1, 942 numDims, ctx.resultCapacity, ctx.resultCapacity, memutils.AsyncCopyDeviceToHost, stream, 0) 943 Ω(dvHost).Should(Equal(dvHostExpected)) 944 }) 945 946 ginkgo.It("prepareTimezoneTable", func() { 947 memStore := new(memMocks.MemStore) 948 memStore.On("GetSchema", mock.Anything).Return(&memstore.TableSchema{ 949 EnumDicts: map[string]memstore.EnumDict{ 950 "timezone": { 951 ReverseDict: []string{"America/Los_Angeles"}, 952 }, 953 }, 954 }, nil) 955 956 utils.Init(common.AresServerConfig{Query: common.QueryConfig{TimezoneTable: common.TimezoneConfig{ 957 TableName: "tableName", 958 }}}, common.NewLoggerFactory().GetDefaultLogger(), common.NewLoggerFactory().GetDefaultLogger(), tally.NewTestScope("test", nil)) 959 qc := &AQLQueryContext{ 960 timezoneTable: timezoneTableContext{tableColumn: "timezone"}, 961 } 962 qc.prepareTimezoneTable(memStore) 963 Ω(qc.Error).Should(BeNil()) 964 Ω(da.(*memoryTrackingDeviceAllocatorImpl).memoryUsage[0]).Should(BeEquivalentTo(2)) 965 deviceFreeAndSetNil(&qc.OOPK.currentBatch.timezoneLookupD) 966 utils.ResetDefaults() 967 }) 968 969 ginkgo.It("ProcessQuery should work", func() { 970 qc := &AQLQueryContext{} 971 q := &AQLQuery{ 972 Table: table, 973 Dimensions: []Dimension{ 974 {Expr: "c0", TimeBucketizer: "m", TimeUnit: "millisecond"}, 975 }, 976 Measures: []Measure{ 977 {Expr: "count(c1)"}, 978 }, 979 TimeFilter: TimeFilter{ 980 Column: "c0", 981 From: "1970-01-01", 982 To: "1970-01-02", 983 }, 984 } 985 qc.Query = q 986 987 qc = q.Compile(memStore, false) 988 Ω(qc.Error).Should(BeNil()) 989 qc.ProcessQuery(memStore) 990 Ω(qc.Error).Should(BeNil()) 991 qc.Results = qc.Postprocess() 992 qc.ReleaseHostResultsBuffers() 993 bs, err := json.Marshal(qc.Results) 994 Ω(err).Should(BeNil()) 995 Ω(bs).Should(MatchJSON(` { 996 "0": 5, 997 "60000": 4, 998 "120000": 3 999 }`)) 1000 1001 bc := qc.OOPK.currentBatch 1002 // Check whether pointers are properly cleaned up. 1003 Ω(len(qc.OOPK.foreignTables)).Should(BeZero()) 1004 Ω(qc.cudaStreams[0]).Should(BeZero()) 1005 Ω(qc.cudaStreams[1]).Should(BeZero()) 1006 1007 Ω(bc.dimensionVectorD[0]).Should(BeZero()) 1008 Ω(bc.dimensionVectorD[1]).Should(BeZero()) 1009 1010 Ω(bc.dimIndexVectorD[0]).Should(BeZero()) 1011 Ω(bc.dimIndexVectorD[1]).Should(BeZero()) 1012 1013 Ω(bc.hashVectorD[0]).Should(BeZero()) 1014 Ω(bc.hashVectorD[1]).Should(BeZero()) 1015 1016 Ω(bc.measureVectorD[0]).Should(BeZero()) 1017 Ω(bc.measureVectorD[1]).Should(BeZero()) 1018 1019 Ω(bc.resultSize).Should(BeZero()) 1020 Ω(bc.resultCapacity).Should(BeZero()) 1021 1022 Ω(len(bc.columns)).Should(BeZero()) 1023 1024 Ω(bc.indexVectorD).Should(BeZero()) 1025 Ω(bc.predicateVectorD).Should(BeZero()) 1026 1027 Ω(bc.size).Should(BeZero()) 1028 1029 Ω(len(bc.foreignTableRecordIDsD)).Should(BeZero()) 1030 Ω(len(bc.exprStackD)).Should(BeZero()) 1031 1032 Ω(qc.OOPK.measureVectorH).Should(BeZero()) 1033 Ω(qc.OOPK.dimensionVectorH).Should(BeZero()) 1034 1035 Ω(qc.OOPK.hllVectorD).Should(BeZero()) 1036 Ω(qc.OOPK.hllDimRegIDCountD).Should(BeZero()) 1037 }) 1038 1039 ginkgo.It("ProcessQuery should work for timezone column queries", func() { 1040 timezoneTable := "table2" 1041 memStore := new(memMocks.MemStore) 1042 1043 mainTableSchema := metaCom.Table{ 1044 Name: table, 1045 Config: metaCom.TableConfig{ 1046 ArchivingDelayMinutes: 500, 1047 ArchivingIntervalMinutes: 300, 1048 }, 1049 IsFactTable: true, 1050 Columns: []metaCom.Column{ 1051 {Deleted: false, Name: "c0", Type: metaCom.Uint32}, 1052 {Deleted: false, Name: "city_id", Type: metaCom.Uint32}, 1053 }, 1054 } 1055 timezoneTableSchema := metaCom.Table{ 1056 Name: timezoneTable, 1057 Config: metaCom.TableConfig{ 1058 ArchivingDelayMinutes: 500, 1059 ArchivingIntervalMinutes: 300, 1060 }, 1061 IsFactTable: false, 1062 Columns: []metaCom.Column{ 1063 {Deleted: false, Name: "id", Type: metaCom.Uint32}, 1064 {Deleted: false, Name: "timezone", Type: metaCom.SmallEnum}, 1065 }, 1066 PrimaryKeyColumns: []int{0}, 1067 } 1068 memStore.On("GetSchemas", mock.Anything).Return(map[string]*memstore.TableSchema{ 1069 table: { 1070 Schema: mainTableSchema, 1071 ColumnIDs: map[string]int{"c0": 0, "city_id": 1}, 1072 ValueTypeByColumn: []memCom.DataType{memCom.Uint32, memCom.Uint32}, 1073 DefaultValues: []*memCom.DataValue{&memCom.NullDataValue, &memCom.NullDataValue}, 1074 }, 1075 timezoneTable: { 1076 Schema: timezoneTableSchema, 1077 ColumnIDs: map[string]int{"id": 0, "timezone": 1}, 1078 ValueTypeByColumn: []memCom.DataType{memCom.Uint32, memCom.SmallEnum}, 1079 DefaultValues: []*memCom.DataValue{&memCom.NullDataValue, &memCom.NullDataValue}, 1080 EnumDicts: map[string]memstore.EnumDict{ 1081 "id": {}, 1082 "timezone": { 1083 ReverseDict: []string{"Africa/Algiers"}, 1084 }, 1085 }, 1086 }, 1087 }) 1088 memStore.On("GetSchema", table).Return(&memstore.TableSchema{ 1089 Schema: mainTableSchema, 1090 ColumnIDs: map[string]int{"c0": 0, "city_id": 1}, 1091 ValueTypeByColumn: []memCom.DataType{memCom.Uint32, memCom.Uint32}, 1092 DefaultValues: []*memCom.DataValue{&memCom.NullDataValue, &memCom.NullDataValue}, 1093 }, nil) 1094 memStore.On("GetSchema", timezoneTable).Return(&memstore.TableSchema{ 1095 Schema: timezoneTableSchema, 1096 ColumnIDs: map[string]int{"id": 0, "timezone": 1}, 1097 ValueTypeByColumn: []memCom.DataType{memCom.Uint32, memCom.SmallEnum}, 1098 DefaultValues: []*memCom.DataValue{&memCom.NullDataValue, &memCom.NullDataValue}, 1099 EnumDicts: map[string]memstore.EnumDict{ 1100 "id": {}, 1101 "timezone": { 1102 ReverseDict: []string{"Africa/Algiers", "", ""}, 1103 }, 1104 }, 1105 }, nil) 1106 memStore.On("RLock").Return(nil) 1107 memStore.On("RUnlock").Return(nil) 1108 1109 timezoneTableShard := memstore.NewTableShard(&memstore.TableSchema{ 1110 Schema: timezoneTableSchema, 1111 ValueTypeByColumn: []memCom.DataType{memCom.Uint32, memCom.SmallEnum}, 1112 DefaultValues: []*memCom.DataValue{&memCom.NullDataValue, &memCom.NullDataValue}, 1113 }, metaStore, diskStore, hostMemoryManager, shardID) 1114 timezoneTableBatch := memstore.LiveBatch{ 1115 Batch: memstore.Batch{ 1116 RWMutex: &sync.RWMutex{}, 1117 Columns: batch120.Columns, 1118 }, 1119 Capacity: 5, 1120 } 1121 timezoneTableShard.LiveStore = &memstore.LiveStore{ 1122 LastReadRecord: memstore.RecordID{BatchID: -90, Index: 0}, 1123 Batches: map[int32]*memstore.LiveBatch{ 1124 -2147483648: &timezoneTableBatch, 1125 }, 1126 PrimaryKey: memstore.NewPrimaryKey(4, false, 5, hostMemoryManager), 1127 HostMemoryManager: hostMemoryManager, 1128 } 1129 // build foreign table primary key index 1130 keyBytes := make([]byte, 4) 1131 recordID := memstore.RecordID{BatchID: -2147483648, Index: 0} 1132 for i := 0; i < 5; i++ { 1133 binary.LittleEndian.PutUint32(keyBytes, 100+uint32(i)*10) 1134 recordID.Index = uint32(i) 1135 timezoneTableShard.LiveStore.PrimaryKey.FindOrInsert(keyBytes, recordID, 0) 1136 } 1137 1138 mainTableShard := memstore.NewTableShard(&memstore.TableSchema{ 1139 Schema: mainTableSchema, 1140 ValueTypeByColumn: []memCom.DataType{memCom.Uint32, memCom.Uint32}, 1141 DefaultValues: []*memCom.DataValue{&memCom.NullDataValue, &memCom.NullDataValue}, 1142 }, metaStore, diskStore, hostMemoryManager, shardID) 1143 mainTableShard.LiveStore = &memstore.LiveStore{ 1144 LastReadRecord: memstore.RecordID{BatchID: -90, Index: 0}, 1145 Batches: map[int32]*memstore.LiveBatch{ 1146 -2147483648: { 1147 Batch: memstore.Batch{ 1148 RWMutex: &sync.RWMutex{}, 1149 Columns: batch130.Columns, 1150 }, 1151 Capacity: 5, 1152 }, 1153 }, 1154 PrimaryKey: memstore.NewPrimaryKey(16, true, 0, hostMemoryManager), 1155 HostMemoryManager: hostMemoryManager, 1156 } 1157 memStore.On("GetTableShard", timezoneTable, 0).Run(func(args mock.Arguments) { 1158 timezoneTableShard.Users.Add(1) 1159 }).Return(timezoneTableShard, nil).Once() 1160 memStore.On("GetTableShard", table, 0).Run(func(args mock.Arguments) { 1161 mainTableShard.Users.Add(1) 1162 }).Return(mainTableShard, nil).Once() 1163 1164 utils.Init(common.AresServerConfig{Query: common.QueryConfig{TimezoneTable: common.TimezoneConfig{ 1165 TableName: timezoneTable, 1166 }}}, common.NewLoggerFactory().GetDefaultLogger(), common.NewLoggerFactory().GetDefaultLogger(), tally.NewTestScope("test", nil)) 1167 1168 qc := &AQLQueryContext{} 1169 q := &AQLQuery{ 1170 Table: table, 1171 Dimensions: []Dimension{ 1172 {Expr: "c0", TimeBucketizer: "3m", TimeUnit: "second"}, 1173 }, 1174 Measures: []Measure{ 1175 {Expr: "count(*)"}, 1176 }, 1177 TimeFilter: TimeFilter{ 1178 Column: "c0", 1179 From: "1970-01-01", 1180 To: "1970-01-02", 1181 }, 1182 Timezone: "timezone(city_id)", 1183 } 1184 qc.Query = q 1185 1186 qc = q.Compile(memStore, false) 1187 Ω(qc.Error).Should(BeNil()) 1188 Ω(qc.TableScanners).Should(HaveLen(2)) 1189 qc.ProcessQuery(memStore) 1190 Ω(qc.Error).Should(BeNil()) 1191 Ω(qc.OOPK.currentBatch.timezoneLookupDSize).Should(Equal(3)) 1192 qc.Results = qc.Postprocess() 1193 qc.ReleaseHostResultsBuffers() 1194 bs, err := json.Marshal(qc.Results) 1195 Ω(err).Should(BeNil()) 1196 Ω(bs).Should(MatchJSON(` { 1197 "0": 4, 1198 "3600": 1 1199 }`)) 1200 1201 bc := qc.OOPK.currentBatch 1202 Ω(bc.timezoneLookupD).Should(BeZero()) 1203 utils.ResetDefaults() 1204 }) 1205 1206 ginkgo.It("dimValResVectorSize should work", func() { 1207 Ω(dimValResVectorSize(3, queryCom.DimCountsPerDimWidth{0, 0, 1, 1, 1})).Should(Equal(30)) 1208 Ω(dimValResVectorSize(3, queryCom.DimCountsPerDimWidth{0, 0, 2, 1, 1})).Should(Equal(45)) 1209 Ω(dimValResVectorSize(3, queryCom.DimCountsPerDimWidth{0, 0, 1, 0, 0})).Should(Equal(15)) 1210 Ω(dimValResVectorSize(3, queryCom.DimCountsPerDimWidth{0, 0, 1, 1, 0})).Should(Equal(24)) 1211 Ω(dimValResVectorSize(3, queryCom.DimCountsPerDimWidth{0, 0, 1, 0, 1})).Should(Equal(21)) 1212 Ω(dimValResVectorSize(3, queryCom.DimCountsPerDimWidth{0, 0, 0, 1, 1})).Should(Equal(15)) 1213 Ω(dimValResVectorSize(3, queryCom.DimCountsPerDimWidth{0, 0, 0, 1, 0})).Should(Equal(9)) 1214 Ω(dimValResVectorSize(3, queryCom.DimCountsPerDimWidth{0, 0, 0, 0, 1})).Should(Equal(6)) 1215 Ω(dimValResVectorSize(0, queryCom.DimCountsPerDimWidth{0, 0, 1, 1, 1})).Should(Equal(0)) 1216 }) 1217 1218 ginkgo.It("getGeoShapeLatLongSlice", func() { 1219 var lats, longs []float32 1220 1221 shape := memCom.GeoShapeGo{ 1222 Polygons: [][]memCom.GeoPointGo{ 1223 { 1224 { 1225 90.0, 1226 -180.0, 1227 }, 1228 { 1229 90.0, 1230 -180.0, 1231 }, 1232 }, 1233 { 1234 { 1235 90.0, 1236 -180.0, 1237 }, 1238 { 1239 90.0, 1240 -180.0, 1241 }, 1242 }, 1243 }, 1244 } 1245 1246 lats, longs, numPoints := getGeoShapeLatLongSlice(lats, longs, shape) 1247 Ω(numPoints).Should(Equal(5)) 1248 expectedLats := []float32{ 1249 90.0, 1250 90.0, 1251 math.MaxFloat32, 1252 90.0, 1253 90.0, 1254 } 1255 expectedLongs := []float32{ 1256 -180.0, 1257 -180.0, 1258 math.MaxFloat32, 1259 -180.0, 1260 -180.0, 1261 } 1262 Ω(lats).Should(Equal(expectedLats)) 1263 Ω(longs).Should(Equal(expectedLongs)) 1264 }) 1265 1266 ginkgo.It("evaluateGeoIntersect should work", func() { 1267 mockMemoryManager := new(memComMocks.HostMemoryManager) 1268 mockMemoryManager.On("ReportUnmanagedSpaceUsageChange", mock.Anything).Return() 1269 1270 // prepare trip table 1271 tripsSchema := &memstore.TableSchema{ 1272 Schema: metaCom.Table{ 1273 Name: "trips", 1274 }, 1275 ColumnIDs: map[string]int{"request_at": 0, "request_point": 1}, 1276 ValueTypeByColumn: []memCom.DataType{memCom.Uint32, memCom.GeoPoint}, 1277 PrimaryKeyColumnTypes: []memCom.DataType{memCom.Uint32}, 1278 PrimaryKeyBytes: 4, 1279 } 1280 tripTimeLiveVP := memstore.NewLiveVectorParty(5, memCom.Uint32, memCom.NullDataValue, mockMemoryManager) 1281 tripTimeLiveVP.Allocate(false) 1282 pointLiveVP := memstore.NewLiveVectorParty(5, memCom.GeoPoint, memCom.NullDataValue, mockMemoryManager) 1283 pointLiveVP.Allocate(false) 1284 1285 // 5 points (0,0),(3,2.5),(1.5, 3.5),(1.5,4.5),null 1286 // in in 2 in 3 out out 1287 points := [4][2]float32{{0, 0}, {3, 2.5}, {1.5, 3.5}, {1.5, 4.5}} 1288 isPointValid := [5]bool{true, true, true, true, false} 1289 for i := 0; i < 5; i++ { 1290 requestTime := uint32(0) 1291 tripTimeLiveVP.SetDataValue(i, memCom.DataValue{Valid: true, OtherVal: unsafe.Pointer(&requestTime)}, memstore.IgnoreCount) 1292 if isPointValid[i] { 1293 pointLiveVP.SetDataValue(i, memCom.DataValue{Valid: true, OtherVal: unsafe.Pointer(&points[i])}, memstore.IgnoreCount) 1294 } else { 1295 pointLiveVP.SetDataValue(i, memCom.NullDataValue, memstore.IgnoreCount) 1296 } 1297 } 1298 1299 tripsTableShard := &memstore.TableShard{ 1300 Schema: tripsSchema, 1301 ArchiveStore: &memstore.ArchiveStore{ 1302 CurrentVersion: memstore.NewArchiveStoreVersion(0, shard), 1303 }, 1304 LiveStore: &memstore.LiveStore{ 1305 Batches: map[int32]*memstore.LiveBatch{ 1306 memstore.BaseBatchID: { 1307 Batch: memstore.Batch{ 1308 RWMutex: &sync.RWMutex{}, 1309 Columns: []memCom.VectorParty{ 1310 tripTimeLiveVP, 1311 pointLiveVP, 1312 }, 1313 }, 1314 }, 1315 }, 1316 LastReadRecord: memstore.RecordID{BatchID: memstore.BaseBatchID, Index: 5}, 1317 }, 1318 HostMemoryManager: mockMemoryManager, 1319 } 1320 1321 // prepare geofence table 1322 geofenceSchema := &memstore.TableSchema{ 1323 Schema: metaCom.Table{ 1324 Name: "geofence", 1325 Config: metaCom.TableConfig{ 1326 InitialPrimaryKeyNumBuckets: 1, 1327 }, 1328 }, 1329 ColumnIDs: map[string]int{"geofence_uuid": 0, "shape": 1}, 1330 ValueTypeByColumn: []memCom.DataType{memCom.UUID, memCom.GeoShape}, 1331 PrimaryKeyColumnTypes: []memCom.DataType{memCom.UUID}, 1332 PrimaryKeyBytes: 16, 1333 } 1334 shapeUUIDs := []string{"00000192F23D460DBE60400C32EA0667", "00001A3F088047D79343894698F221AB", "0000334BB6B0420986175F20F3FBF90D"} 1335 shapes := []memCom.GeoShapeGo{ 1336 { 1337 Polygons: [][]memCom.GeoPointGo{ 1338 { 1339 {1, 1}, {1, -1}, {-1, -1}, {-1, 1}, {1, 1}, 1340 }, 1341 }, 1342 }, 1343 { 1344 Polygons: [][]memCom.GeoPointGo{ 1345 { 1346 {3, 3}, {2, 2}, {4, 2}, {3, 3}, 1347 }, 1348 }, 1349 }, 1350 { 1351 Polygons: [][]memCom.GeoPointGo{ 1352 { 1353 {0, 6}, {3, 6}, {3, 3}, {0, 3}, {0, 6}, 1354 }, 1355 { 1356 {1, 5}, {2, 5}, {2, 4}, {1, 4}, {1, 5}, 1357 }, 1358 }, 1359 }, 1360 } 1361 shapeUUIDLiveVP := memstore.NewLiveVectorParty(3, memCom.UUID, memCom.NullDataValue, mockMemoryManager) 1362 shapeUUIDLiveVP.Allocate(false) 1363 shapeLiveVP := memstore.NewLiveVectorParty(3, memCom.GeoShape, memCom.NullDataValue, mockMemoryManager) 1364 shapeLiveVP.Allocate(false) 1365 1366 geoFenceTableShard := &memstore.TableShard{ 1367 Schema: geofenceSchema, 1368 HostMemoryManager: mockMemoryManager, 1369 } 1370 geoFenceLiveStore := memstore.NewLiveStore(10, geoFenceTableShard) 1371 geoFenceLiveStore.Batches = map[int32]*memstore.LiveBatch{ 1372 memstore.BaseBatchID: { 1373 Batch: memstore.Batch{ 1374 RWMutex: &sync.RWMutex{}, 1375 Columns: []memCom.VectorParty{ 1376 shapeUUIDLiveVP, 1377 shapeLiveVP, 1378 }, 1379 }, 1380 }, 1381 } 1382 geoFenceLiveStore.LastReadRecord = memstore.RecordID{BatchID: memstore.BaseBatchID, Index: 4} 1383 geoFenceTableShard.LiveStore = geoFenceLiveStore 1384 for i := 0; i < 3; i++ { 1385 uuidValue, _ := memCom.ValueFromString(shapeUUIDs[i], memCom.UUID) 1386 shapeUUIDLiveVP.SetDataValue(i, uuidValue, memstore.IgnoreCount) 1387 shapeLiveVP.SetDataValue(i, memCom.DataValue{Valid: true, GoVal: &shapes[i]}, memstore.IgnoreCount) 1388 key, err := memstore.GetPrimaryKeyBytes([]memCom.DataValue{uuidValue}, 16) 1389 Ω(err).Should(BeNil()) 1390 geoFenceLiveStore.PrimaryKey.FindOrInsert( 1391 key, 1392 memstore.RecordID{ 1393 BatchID: memstore.BaseBatchID, 1394 Index: uint32(i)}, 1395 0) 1396 } 1397 1398 mockMemStore := new(memMocks.MemStore) 1399 mockMemStore.On("GetTableShard", "geofence", 0).Run(func(args mock.Arguments) { 1400 geoFenceTableShard.Users.Add(1) 1401 }).Return(geoFenceTableShard, nil).Once() 1402 1403 mockMemStore.On("GetTableShard", "trips", 0).Run(func(args mock.Arguments) { 1404 tripsTableShard.Users.Add(1) 1405 }).Return(tripsTableShard, nil).Once() 1406 1407 mockMemStore.On("RLock").Return() 1408 mockMemStore.On("RUnlock").Return() 1409 1410 qc := AQLQueryContext{ 1411 Query: &AQLQuery{ 1412 Table: "trips", 1413 Dimensions: []Dimension{ 1414 {Expr: "request_at"}, 1415 }, 1416 Measures: []Measure{ 1417 {Expr: "count(1)"}, 1418 }, 1419 TimeFilter: TimeFilter{ 1420 Column: "request_at", 1421 From: "0", 1422 To: "86400", 1423 }, 1424 }, 1425 TableScanners: []*TableScanner{ 1426 { 1427 Columns: []int{0, 1}, 1428 ColumnsByIDs: map[int]int{ 1429 0: 0, 1430 1: 1, 1431 }, 1432 ColumnUsages: map[int]columnUsage{ 1433 0: columnUsedByAllBatches, 1434 1: columnUsedByAllBatches, 1435 }, 1436 Schema: tripsSchema, 1437 ArchiveBatchIDStart: 0, 1438 ArchiveBatchIDEnd: 1, 1439 Shards: []int{0}, 1440 }, 1441 { 1442 ColumnsByIDs: map[int]int{ 1443 0: 0, 1444 1: 1, 1445 }, 1446 ColumnUsages: map[int]columnUsage{ 1447 1: columnUsedByAllBatches, 1448 }, 1449 Schema: geofenceSchema, 1450 }, 1451 }, 1452 OOPK: OOPKContext{ 1453 DimRowBytes: 5, 1454 DimensionVectorIndex: []int{0}, 1455 NumDimsPerDimWidth: queryCom.DimCountsPerDimWidth{0, 0, 1, 0, 0}, 1456 TimeFilters: [2]expr.Expr{ 1457 &expr.BinaryExpr{ 1458 ExprType: expr.Boolean, 1459 Op: expr.GTE, 1460 LHS: &expr.VarRef{ 1461 Val: "request_at", 1462 ExprType: expr.Unsigned, 1463 TableID: 0, 1464 ColumnID: 0, 1465 DataType: memCom.Uint32, 1466 }, 1467 RHS: &expr.NumberLiteral{ 1468 Int: 0, 1469 Expr: strconv.FormatInt(0, 10), 1470 ExprType: expr.Unsigned, 1471 }, 1472 }, 1473 &expr.BinaryExpr{ 1474 ExprType: expr.Boolean, 1475 Op: expr.LT, 1476 LHS: &expr.VarRef{ 1477 Val: "request_at", 1478 ExprType: expr.Unsigned, 1479 TableID: 0, 1480 ColumnID: 0, 1481 DataType: memCom.Uint32, 1482 }, 1483 RHS: &expr.NumberLiteral{ 1484 Int: 86400, 1485 Expr: strconv.FormatInt(86400, 10), 1486 ExprType: expr.Unsigned, 1487 }, 1488 }, 1489 }, 1490 Dimensions: []expr.Expr{ 1491 &expr.VarRef{ 1492 Val: "request_at", 1493 ExprType: expr.Unsigned, 1494 TableID: 0, 1495 ColumnID: 0, 1496 DataType: memCom.Uint32, 1497 }, 1498 }, 1499 AggregateType: 1, 1500 MeasureBytes: 4, 1501 Measure: &expr.NumberLiteral{ 1502 Val: 1, 1503 Int: 1, 1504 Expr: "1", 1505 ExprType: expr.Unsigned, 1506 }, 1507 geoIntersection: &geoIntersection{ 1508 shapeTableID: 1, 1509 shapeColumnID: 1, 1510 pointColumnID: 1, 1511 shapeUUIDs: shapeUUIDs, 1512 inOrOut: false, 1513 dimIndex: -1, 1514 }, 1515 }, 1516 fromTime: &alignedTime{time.Unix(0, 0), "s"}, 1517 toTime: &alignedTime{time.Unix(86400, 0), "s"}, 1518 } 1519 1520 qc.ProcessQuery(mockMemStore) 1521 Ω(qc.Error).Should(BeNil()) 1522 qc.Results = qc.Postprocess() 1523 Ω(qc.Error).Should(BeNil()) 1524 bs, err := json.Marshal(qc.Results) 1525 Ω(err).Should(BeNil()) 1526 Ω(bs).Should(MatchJSON( 1527 `{ 1528 "0": 1 1529 }`, 1530 )) 1531 qc.ReleaseHostResultsBuffers() 1532 }) 1533 1534 ginkgo.It("evaluateGeoIntersectJoin should work", func() { 1535 mockMemoryManager := new(memComMocks.HostMemoryManager) 1536 mockMemoryManager.On("ReportUnmanagedSpaceUsageChange", mock.Anything).Return() 1537 1538 // prepare trip table 1539 tripsSchema := &memstore.TableSchema{ 1540 Schema: metaCom.Table{ 1541 Name: "trips", 1542 }, 1543 ColumnIDs: map[string]int{"request_at": 0, "request_point": 1}, 1544 ValueTypeByColumn: []memCom.DataType{memCom.Uint32, memCom.GeoPoint}, 1545 PrimaryKeyColumnTypes: []memCom.DataType{memCom.Uint32}, 1546 PrimaryKeyBytes: 4, 1547 } 1548 tripTimeLiveVP := memstore.NewLiveVectorParty(5, memCom.Uint32, memCom.NullDataValue, mockMemoryManager) 1549 tripTimeLiveVP.Allocate(false) 1550 pointLiveVP := memstore.NewLiveVectorParty(5, memCom.GeoPoint, memCom.NullDataValue, mockMemoryManager) 1551 pointLiveVP.Allocate(false) 1552 1553 // 5 points (0,0),(3,2.5),(1.5, 3.5),(1.5,4.5),null 1554 // in in 2 in 3 out out 1555 points := [4][2]float32{{0, 0}, {3, 2.5}, {1.5, 3.5}, {1.5, 4.5}} 1556 isPointValid := [5]bool{true, true, true, true, false} 1557 for i := 0; i < 5; i++ { 1558 requestTime := uint32(0) 1559 tripTimeLiveVP.SetDataValue(i, memCom.DataValue{Valid: true, OtherVal: unsafe.Pointer(&requestTime)}, memstore.IgnoreCount) 1560 if isPointValid[i] { 1561 pointLiveVP.SetDataValue(i, memCom.DataValue{Valid: true, OtherVal: unsafe.Pointer(&points[i])}, memstore.IgnoreCount) 1562 } else { 1563 pointLiveVP.SetDataValue(i, memCom.NullDataValue, memstore.IgnoreCount) 1564 } 1565 } 1566 1567 tripsTableShard := &memstore.TableShard{ 1568 Schema: tripsSchema, 1569 ArchiveStore: &memstore.ArchiveStore{ 1570 CurrentVersion: memstore.NewArchiveStoreVersion(0, shard), 1571 }, 1572 LiveStore: &memstore.LiveStore{ 1573 Batches: map[int32]*memstore.LiveBatch{ 1574 memstore.BaseBatchID: { 1575 Batch: memstore.Batch{ 1576 RWMutex: &sync.RWMutex{}, 1577 Columns: []memCom.VectorParty{ 1578 tripTimeLiveVP, 1579 pointLiveVP, 1580 }, 1581 }, 1582 }, 1583 }, 1584 LastReadRecord: memstore.RecordID{BatchID: memstore.BaseBatchID, Index: 5}, 1585 }, 1586 HostMemoryManager: mockMemoryManager, 1587 } 1588 1589 // prepare geofence table 1590 geofenceSchema := &memstore.TableSchema{ 1591 Schema: metaCom.Table{ 1592 Name: "geofence", 1593 Config: metaCom.TableConfig{ 1594 InitialPrimaryKeyNumBuckets: 1, 1595 }, 1596 }, 1597 ColumnIDs: map[string]int{"geofence_uuid": 0, "shape": 1}, 1598 ValueTypeByColumn: []memCom.DataType{memCom.UUID, memCom.GeoShape}, 1599 PrimaryKeyColumnTypes: []memCom.DataType{memCom.UUID}, 1600 PrimaryKeyBytes: 16, 1601 } 1602 shapeUUIDs := []string{"00000192F23D460DBE60400C32EA0667", "00001A3F088047D79343894698F221AB", "0000334BB6B0420986175F20F3FBF90D"} 1603 shapes := []memCom.GeoShapeGo{ 1604 { 1605 Polygons: [][]memCom.GeoPointGo{ 1606 { 1607 {1, 1}, {1, -1}, {-1, -1}, {-1, 1}, {1, 1}, 1608 }, 1609 }, 1610 }, 1611 { 1612 Polygons: [][]memCom.GeoPointGo{ 1613 { 1614 {3, 3}, {2, 2}, {4, 2}, {3, 3}, 1615 }, 1616 }, 1617 }, 1618 { 1619 Polygons: [][]memCom.GeoPointGo{ 1620 { 1621 {0, 6}, {3, 6}, {3, 3}, {0, 3}, {0, 6}, 1622 }, 1623 { 1624 {1, 5}, {2, 5}, {2, 4}, {1, 4}, {1, 5}, 1625 }, 1626 }, 1627 }, 1628 } 1629 shapeUUIDLiveVP := memstore.NewLiveVectorParty(3, memCom.UUID, memCom.NullDataValue, mockMemoryManager) 1630 shapeUUIDLiveVP.Allocate(false) 1631 shapeLiveVP := memstore.NewLiveVectorParty(3, memCom.GeoShape, memCom.NullDataValue, mockMemoryManager) 1632 shapeLiveVP.Allocate(false) 1633 1634 geoFenceTableShard := &memstore.TableShard{ 1635 Schema: geofenceSchema, 1636 HostMemoryManager: mockMemoryManager, 1637 } 1638 geoFenceLiveStore := memstore.NewLiveStore(10, geoFenceTableShard) 1639 geoFenceLiveStore.Batches = map[int32]*memstore.LiveBatch{ 1640 memstore.BaseBatchID: { 1641 Batch: memstore.Batch{ 1642 RWMutex: &sync.RWMutex{}, 1643 Columns: []memCom.VectorParty{ 1644 shapeUUIDLiveVP, 1645 shapeLiveVP, 1646 }, 1647 }, 1648 }, 1649 } 1650 geoFenceLiveStore.LastReadRecord = memstore.RecordID{BatchID: memstore.BaseBatchID, Index: 4} 1651 geoFenceTableShard.LiveStore = geoFenceLiveStore 1652 for i := 0; i < 3; i++ { 1653 uuidValue, _ := memCom.ValueFromString(shapeUUIDs[i], memCom.UUID) 1654 shapeUUIDLiveVP.SetDataValue(i, uuidValue, memstore.IgnoreCount) 1655 shapeLiveVP.SetDataValue(i, memCom.DataValue{Valid: true, GoVal: &shapes[i]}, memstore.IgnoreCount) 1656 key, err := memstore.GetPrimaryKeyBytes([]memCom.DataValue{uuidValue}, 16) 1657 Ω(err).Should(BeNil()) 1658 geoFenceLiveStore.PrimaryKey.FindOrInsert( 1659 key, 1660 memstore.RecordID{ 1661 BatchID: memstore.BaseBatchID, 1662 Index: uint32(i)}, 1663 0) 1664 } 1665 1666 mockMemStore := new(memMocks.MemStore) 1667 mockMemStore.On("GetTableShard", "geofence", 0).Run(func(args mock.Arguments) { 1668 geoFenceTableShard.Users.Add(1) 1669 }).Return(geoFenceTableShard, nil).Once() 1670 1671 mockMemStore.On("GetTableShard", "trips", 0).Run(func(args mock.Arguments) { 1672 tripsTableShard.Users.Add(1) 1673 }).Return(tripsTableShard, nil).Once() 1674 1675 mockMemStore.On("RLock").Return() 1676 mockMemStore.On("RUnlock").Return() 1677 1678 qc := AQLQueryContext{ 1679 Query: &AQLQuery{ 1680 Table: "trips", 1681 Dimensions: []Dimension{ 1682 {Expr: "request_at"}, 1683 {Expr: "geo_uuid"}, 1684 }, 1685 Measures: []Measure{ 1686 {Expr: "count(1)"}, 1687 }, 1688 TimeFilter: TimeFilter{ 1689 Column: "request_at", 1690 From: "0", 1691 To: "86400", 1692 }, 1693 }, 1694 TableScanners: []*TableScanner{ 1695 { 1696 Columns: []int{0, 1}, 1697 ColumnsByIDs: map[int]int{ 1698 0: 0, 1699 1: 1, 1700 }, 1701 ColumnUsages: map[int]columnUsage{ 1702 0: columnUsedByAllBatches, 1703 1: columnUsedByAllBatches, 1704 }, 1705 Schema: tripsSchema, 1706 ArchiveBatchIDStart: 0, 1707 ArchiveBatchIDEnd: 1, 1708 Shards: []int{0}, 1709 }, 1710 { 1711 ColumnsByIDs: map[int]int{ 1712 0: 0, 1713 1: 1, 1714 }, 1715 ColumnUsages: map[int]columnUsage{ 1716 1: columnUsedByAllBatches, 1717 }, 1718 Schema: geofenceSchema, 1719 }, 1720 }, 1721 OOPK: OOPKContext{ 1722 DimRowBytes: 7, 1723 DimensionVectorIndex: []int{0, 1}, 1724 NumDimsPerDimWidth: queryCom.DimCountsPerDimWidth{0, 0, 1, 0, 1}, 1725 TimeFilters: [2]expr.Expr{ 1726 &expr.BinaryExpr{ 1727 ExprType: expr.Boolean, 1728 Op: expr.GTE, 1729 LHS: &expr.VarRef{ 1730 Val: "request_at", 1731 ExprType: expr.Unsigned, 1732 TableID: 0, 1733 ColumnID: 0, 1734 DataType: memCom.Uint32, 1735 }, 1736 RHS: &expr.NumberLiteral{ 1737 Int: 0, 1738 Expr: strconv.FormatInt(0, 10), 1739 ExprType: expr.Unsigned, 1740 }, 1741 }, 1742 &expr.BinaryExpr{ 1743 ExprType: expr.Boolean, 1744 Op: expr.LT, 1745 LHS: &expr.VarRef{ 1746 Val: "request_at", 1747 ExprType: expr.Unsigned, 1748 TableID: 0, 1749 ColumnID: 0, 1750 DataType: memCom.Uint32, 1751 }, 1752 RHS: &expr.NumberLiteral{ 1753 Int: 86400, 1754 Expr: strconv.FormatInt(86400, 10), 1755 ExprType: expr.Unsigned, 1756 }, 1757 }, 1758 }, 1759 Dimensions: []expr.Expr{ 1760 &expr.VarRef{ 1761 Val: "request_at", 1762 ExprType: expr.Unsigned, 1763 TableID: 0, 1764 ColumnID: 0, 1765 DataType: memCom.Uint32, 1766 }, 1767 &expr.VarRef{ 1768 Val: "geo_uuid", 1769 ExprType: expr.GeoShape, 1770 TableID: 0, 1771 ColumnID: 0, 1772 DataType: memCom.Uint8, 1773 }, 1774 }, 1775 AggregateType: 1, 1776 MeasureBytes: 4, 1777 Measure: &expr.NumberLiteral{ 1778 Val: 1, 1779 Int: 1, 1780 Expr: "1", 1781 ExprType: expr.Unsigned, 1782 }, 1783 geoIntersection: &geoIntersection{ 1784 shapeTableID: 1, 1785 shapeColumnID: 1, 1786 pointColumnID: 1, 1787 shapeUUIDs: shapeUUIDs, 1788 dimIndex: 1, 1789 inOrOut: true, 1790 }, 1791 }, 1792 fromTime: &alignedTime{time.Unix(0, 0), "s"}, 1793 toTime: &alignedTime{time.Unix(86400, 0), "s"}, 1794 } 1795 1796 qc.ProcessQuery(mockMemStore) 1797 Ω(qc.Error).Should(BeNil()) 1798 qc.Results = qc.Postprocess() 1799 Ω(qc.Error).Should(BeNil()) 1800 bs, err := json.Marshal(qc.Results) 1801 Ω(err).Should(BeNil()) 1802 Ω(bs).Should(MatchJSON( 1803 `{ 1804 "0": { 1805 "00000192F23D460DBE60400C32EA0667": 1, 1806 "00001A3F088047D79343894698F221AB": 1, 1807 "0000334BB6B0420986175F20F3FBF90D": 1 1808 } 1809 }`, 1810 )) 1811 qc.ReleaseHostResultsBuffers() 1812 }) 1813 1814 ginkgo.It("shouldSkipLiveBatch should work", func() { 1815 qc := &AQLQueryContext{} 1816 1817 column0 := new(memComMocks.LiveVectorParty) 1818 column0.On("GetMinMaxValue").Return(uint32(10), uint32(50)) 1819 column1 := new(memComMocks.LiveVectorParty) 1820 column1.On("GetMinMaxValue").Return(uint32(50), uint32(99)) 1821 1822 batch := &memstore.LiveBatch{ 1823 Batch: memstore.Batch{ 1824 RWMutex: &sync.RWMutex{}, 1825 Columns: []memCom.VectorParty{ 1826 column0, 1827 column1, 1828 nil, 1829 }, 1830 }, 1831 } 1832 1833 // No candidate filter. 1834 Ω(qc.shouldSkipLiveBatch(batch)).Should(BeFalse()) 1835 1836 qc.OOPK.MainTableCommonFilters = append(qc.OOPK.MainTableCommonFilters, &expr.UnaryExpr{}) 1837 1838 // UnaryExpr does not match. 1839 Ω(qc.shouldSkipLiveBatch(batch)).Should(BeFalse()) 1840 1841 // we will swap lhs and rhs. 1842 // we will need skip this batch as column 0 does not pass the check. 1843 qc.OOPK.MainTableCommonFilters = append(qc.OOPK.MainTableCommonFilters, &expr.BinaryExpr{ 1844 Op: expr.LT, 1845 RHS: &expr.VarRef{ 1846 ColumnID: 0, 1847 DataType: memCom.Uint32, 1848 }, 1849 LHS: &expr.NumberLiteral{ 1850 Int: 100, 1851 }, 1852 }) 1853 1854 Ω(qc.shouldSkipLiveBatch(batch)).Should(BeTrue()) 1855 1856 // We will pass this check 1857 qc.OOPK.MainTableCommonFilters = []expr.Expr{&expr.BinaryExpr{ 1858 Op: expr.GT, 1859 LHS: &expr.VarRef{ 1860 ColumnID: 1, 1861 DataType: memCom.Uint32, 1862 }, 1863 RHS: &expr.NumberLiteral{ 1864 Int: 50, 1865 }, 1866 }} 1867 Ω(qc.shouldSkipLiveBatch(batch)).Should(BeFalse()) 1868 1869 // This filter is not uint32. 1870 qc.OOPK.MainTableCommonFilters = append(qc.OOPK.MainTableCommonFilters, &expr.BinaryExpr{ 1871 Op: expr.LT, 1872 LHS: &expr.VarRef{ 1873 ColumnID: 0, 1874 DataType: memCom.Uint16, 1875 }, 1876 RHS: &expr.NumberLiteral{ 1877 Int: 5, 1878 }, 1879 }) 1880 1881 Ω(qc.shouldSkipLiveBatch(batch)).Should(BeFalse()) 1882 1883 // column 2 is nil, so we should skip. 1884 qc.OOPK.MainTableCommonFilters = append(qc.OOPK.MainTableCommonFilters, &expr.BinaryExpr{ 1885 Op: expr.LT, 1886 LHS: &expr.VarRef{ 1887 ColumnID: 2, 1888 DataType: memCom.Uint32, 1889 }, 1890 RHS: &expr.NumberLiteral{ 1891 Int: 5, 1892 }, 1893 }) 1894 1895 Ω(qc.shouldSkipLiveBatch(batch)).Should(BeTrue()) 1896 1897 qc.OOPK.MainTableCommonFilters = nil 1898 1899 // we will fail to pass time filter. 1900 qc.OOPK.TimeFilters = [2]expr.Expr{ 1901 &expr.BinaryExpr{ 1902 Op: expr.GTE, 1903 LHS: &expr.VarRef{ 1904 ColumnID: 0, 1905 DataType: memCom.Uint32, 1906 }, 1907 RHS: &expr.NumberLiteral{ 1908 Int: 100, 1909 }, 1910 }, 1911 &expr.BinaryExpr{ 1912 Op: expr.LT, 1913 LHS: &expr.VarRef{ 1914 ColumnID: 0, 1915 DataType: memCom.Uint32, 1916 }, 1917 RHS: &expr.NumberLiteral{ 1918 Int: 200, 1919 }, 1920 }, 1921 } 1922 1923 Ω(qc.shouldSkipLiveBatch(batch)).Should(BeTrue()) 1924 }) 1925 1926 ginkgo.It("evaluateGeoPoint query should work", func() { 1927 mockMemoryManager := new(memComMocks.HostMemoryManager) 1928 mockMemoryManager.On("ReportUnmanagedSpaceUsageChange", mock.Anything).Return() 1929 1930 // prepare trip table 1931 tripsSchema := &memstore.TableSchema{ 1932 Schema: metaCom.Table{ 1933 Name: "trips", 1934 }, 1935 ColumnIDs: map[string]int{"request_at": 0, "request_point": 1}, 1936 ValueTypeByColumn: []memCom.DataType{memCom.Uint32, memCom.GeoPoint}, 1937 PrimaryKeyColumnTypes: []memCom.DataType{memCom.Uint32}, 1938 PrimaryKeyBytes: 4, 1939 } 1940 tripTimeLiveVP := memstore.NewLiveVectorParty(6, memCom.Uint32, memCom.NullDataValue, mockMemoryManager) 1941 tripTimeLiveVP.Allocate(false) 1942 pointLiveVP := memstore.NewLiveVectorParty(6, memCom.GeoPoint, memCom.NullDataValue, mockMemoryManager) 1943 pointLiveVP.Allocate(false) 1944 1945 points := [5][2]float32{{0, 0}, {1.5, 3.5}, {1.5, 3.5}, {37.617994, -122.386177}, {37.617994, -122.386177}} 1946 isPointValid := [6]bool{true, true, true, true, true, false} 1947 for i := 0; i < 6; i++ { 1948 requestTime := uint32(0) 1949 tripTimeLiveVP.SetDataValue(i, memCom.DataValue{Valid: true, OtherVal: unsafe.Pointer(&requestTime)}, memstore.IgnoreCount) 1950 if isPointValid[i] { 1951 pointLiveVP.SetDataValue(i, memCom.DataValue{Valid: true, OtherVal: unsafe.Pointer(&points[i])}, memstore.IgnoreCount) 1952 } else { 1953 pointLiveVP.SetDataValue(i, memCom.NullDataValue, memstore.IgnoreCount) 1954 } 1955 } 1956 1957 tripsTableShard := &memstore.TableShard{ 1958 Schema: tripsSchema, 1959 ArchiveStore: &memstore.ArchiveStore{ 1960 CurrentVersion: memstore.NewArchiveStoreVersion(0, shard), 1961 }, 1962 LiveStore: &memstore.LiveStore{ 1963 Batches: map[int32]*memstore.LiveBatch{ 1964 memstore.BaseBatchID: { 1965 Batch: memstore.Batch{ 1966 RWMutex: &sync.RWMutex{}, 1967 Columns: []memCom.VectorParty{ 1968 tripTimeLiveVP, 1969 pointLiveVP, 1970 }, 1971 }, 1972 }, 1973 }, 1974 LastReadRecord: memstore.RecordID{BatchID: memstore.BaseBatchID, Index: 5}, 1975 }, 1976 HostMemoryManager: mockMemoryManager, 1977 } 1978 1979 mockMemStore := new(memMocks.MemStore) 1980 1981 mockMemStore.On("GetTableShard", "trips", 0).Run(func(args mock.Arguments) { 1982 tripsTableShard.Users.Add(1) 1983 }).Return(tripsTableShard, nil).Once() 1984 1985 mockMemStore.On("RLock").Return() 1986 mockMemStore.On("RUnlock").Return() 1987 1988 qc := AQLQueryContext{ 1989 Query: &AQLQuery{ 1990 Table: "trips", 1991 Dimensions: []Dimension{ 1992 {Expr: "request_at"}, 1993 }, 1994 Measures: []Measure{ 1995 {Expr: "count(1)"}, 1996 }, 1997 }, 1998 TableScanners: []*TableScanner{ 1999 { 2000 Columns: []int{0, 1}, 2001 ColumnsByIDs: map[int]int{ 2002 0: 0, 2003 1: 1, 2004 }, 2005 ColumnUsages: map[int]columnUsage{ 2006 0: columnUsedByAllBatches, 2007 1: columnUsedByAllBatches, 2008 }, 2009 Schema: tripsSchema, 2010 ArchiveBatchIDStart: 0, 2011 ArchiveBatchIDEnd: 1, 2012 Shards: []int{0}, 2013 }, 2014 }, 2015 OOPK: OOPKContext{ 2016 DimRowBytes: 5, 2017 DimensionVectorIndex: []int{0}, 2018 NumDimsPerDimWidth: queryCom.DimCountsPerDimWidth{0, 0, 1, 0, 0}, 2019 Prefilters: []expr.Expr{ 2020 &expr.BinaryExpr{ 2021 Op: expr.EQ, 2022 LHS: &expr.VarRef{Val: "request_point", ColumnID: 1, TableID: 0, ExprType: expr.GeoPoint, DataType: memCom.GeoPoint}, 2023 RHS: &expr.GeopointLiteral{Val: [2]float32{37.617994, -122.386177}}, 2024 ExprType: expr.Boolean, 2025 }, 2026 }, 2027 Dimensions: []expr.Expr{ 2028 &expr.VarRef{ 2029 Val: "request_at", 2030 ExprType: expr.Unsigned, 2031 TableID: 0, 2032 ColumnID: 0, 2033 DataType: memCom.Uint32, 2034 }, 2035 }, 2036 AggregateType: 1, 2037 MeasureBytes: 4, 2038 Measure: &expr.NumberLiteral{ 2039 Val: 1, 2040 Int: 1, 2041 Expr: "1", 2042 ExprType: expr.Unsigned, 2043 }, 2044 }, 2045 fromTime: &alignedTime{time.Unix(0, 0), "s"}, 2046 toTime: &alignedTime{time.Unix(86400, 0), "s"}, 2047 } 2048 2049 qc.ProcessQuery(mockMemStore) 2050 Ω(qc.Error).Should(BeNil()) 2051 qc.Results = qc.Postprocess() 2052 Ω(qc.Error).Should(BeNil()) 2053 bs, err := json.Marshal(qc.Results) 2054 Ω(err).Should(BeNil()) 2055 Ω(bs).Should(MatchJSON( 2056 `{ 2057 "0": 2 2058 }`, 2059 )) 2060 qc.ReleaseHostResultsBuffers() 2061 }) 2062 2063 ginkgo.It("ProcessQuery for non-aggregation query should work", func() { 2064 shard.ArchiveStore.CurrentVersion.Batches[0] = archiveBatch1 2065 qc := &AQLQueryContext{} 2066 q := &AQLQuery{ 2067 Table: table, 2068 Dimensions: []Dimension{ 2069 {Expr: "c0"}, 2070 {Expr: "c1"}, 2071 {Expr: "c2"}, 2072 }, 2073 Measures: []Measure{ 2074 {Expr: "1"}, 2075 }, 2076 TimeFilter: TimeFilter{ 2077 Column: "c0", 2078 From: "1970-01-01", 2079 To: "1970-01-02", 2080 }, 2081 Limit: 10, 2082 } 2083 qc.Query = q 2084 2085 qc = q.Compile(memStore, false) 2086 Ω(qc.Error).Should(BeNil()) 2087 qc.ProcessQuery(memStore) 2088 Ω(qc.Error).Should(BeNil()) 2089 2090 qc.Results = qc.Postprocess() 2091 qc.ReleaseHostResultsBuffers() 2092 bs, err := json.Marshal(qc.Results) 2093 Ω(err).Should(BeNil()) 2094 2095 Ω(bs).Should(MatchJSON(` { 2096 "headers": ["c0", "c1", "c2"], 2097 "matrixData": [ 2098 ["100", "0", "1"], 2099 ["110", "1", "NULL" ], 2100 ["120", "NULL", "1.2"], 2101 ["130", "0", "1.3"], 2102 ["100", "0", "NULL"], 2103 ["110", "1", "1.1"], 2104 ["120", "0", "1.2"], 2105 ["0", "NULL", "NULL"], 2106 ["10", "NULL", "1.1"], 2107 ["20", "NULL", "1.2"] 2108 ] 2109 }`)) 2110 2111 bc := qc.OOPK.currentBatch 2112 // Check whether pointers are properly cleaned up. 2113 Ω(len(qc.OOPK.foreignTables)).Should(BeZero()) 2114 Ω(qc.cudaStreams[0]).Should(BeZero()) 2115 Ω(qc.cudaStreams[1]).Should(BeZero()) 2116 2117 Ω(bc.dimensionVectorD[0]).Should(BeZero()) 2118 Ω(bc.dimensionVectorD[1]).Should(BeZero()) 2119 2120 Ω(bc.dimIndexVectorD[0]).Should(BeZero()) 2121 Ω(bc.dimIndexVectorD[1]).Should(BeZero()) 2122 2123 Ω(bc.hashVectorD[0]).Should(BeZero()) 2124 Ω(bc.hashVectorD[1]).Should(BeZero()) 2125 2126 Ω(bc.measureVectorD[0]).Should(BeZero()) 2127 Ω(bc.measureVectorD[1]).Should(BeZero()) 2128 2129 Ω(bc.resultSize).Should(BeZero()) 2130 Ω(bc.resultCapacity).Should(BeZero()) 2131 2132 Ω(len(bc.columns)).Should(BeZero()) 2133 2134 Ω(bc.indexVectorD).Should(BeZero()) 2135 Ω(bc.predicateVectorD).Should(BeZero()) 2136 2137 Ω(bc.size).Should(BeZero()) 2138 2139 Ω(len(bc.foreignTableRecordIDsD)).Should(BeZero()) 2140 Ω(len(bc.exprStackD)).Should(BeZero()) 2141 2142 Ω(qc.OOPK.measureVectorH).Should(BeZero()) 2143 Ω(qc.OOPK.dimensionVectorH).Should(BeZero()) 2144 2145 Ω(qc.OOPK.hllVectorD).Should(BeZero()) 2146 Ω(qc.OOPK.hllDimRegIDCountD).Should(BeZero()) 2147 }) 2148 2149 ginkgo.It("ProcessQuery should work for query without regular filters", func() { 2150 shard.ArchiveStore.CurrentVersion.Batches[0] = archiveBatch1 2151 qc := &AQLQueryContext{} 2152 q := &AQLQuery{ 2153 Table: table, 2154 Dimensions: []Dimension{ 2155 {Expr: "0"}, 2156 }, 2157 Measures: []Measure{ 2158 {Expr: "count(*)"}, 2159 }, 2160 TimeFilter: TimeFilter{ 2161 Column: "c0", 2162 From: "1970-01-01", 2163 To: "1970-01-02", 2164 }, 2165 } 2166 qc.Query = q 2167 qc = q.Compile(memStore, false) 2168 Ω(qc.Error).Should(BeNil()) 2169 qc.ProcessQuery(memStore) 2170 Ω(qc.Error).Should(BeNil()) 2171 2172 qc.Results = qc.Postprocess() 2173 qc.ReleaseHostResultsBuffers() 2174 bs, err := json.Marshal(qc.Results) 2175 Ω(err).Should(BeNil()) 2176 2177 Ω(bs).Should(MatchJSON(` { 2178 "0": 12 2179 }`)) 2180 }) 2181 })