mirror of
https://github.com/hanzoai/traces.git
synced 2026-10-30 18:20:41 +00:00
* Add operators IN, NOT IN, MATCH ANY, and MATCH NONE
* Implement Static.append()
* Print string arrays with '`' instead of '"'
Example ["aa", "bb"] -> [`aa`, `bb`]
* Rewrite binary operations to array equivalent
The rewriter handles the following cases:
- { .a = "a" || .a = "b" } => { .a IN ["a", "b"] }
- { .a != "a" && .a != "b" } => { .a NOT IN ["a", "b"] }
- { .a =~ "a" || .a =~ "b" } => { .a MATCH ANY ["a", "b"] }
- { .a !~ "a" && .a !~ "b" } => { .a MATCH NONE ["a", "b"] }
* Add test cases with arrays to TestBinOp
* traceql.Parse() applies AST optimizations by default
* Rename predicate_test.go to predicates_test.go
* Add array predicates to parquetquery
* BREAKING CHANGE: more precise regex validation
BinaryOperation.validate() considered everythin a valid regex where
FieldExpression.EncodeToString(false) happened to return a valid regex.
With this change the RHS of a regex operation is required to be a string
or string array
* vp4: handle predicates with arrays correctly
* vp5: handle predicates with arrays correctly
* vp3: handle predicates with arrays correctly
* Add test cases for optimized queries
* Update query test examples with optimizable queries
* vp3: fix handling of array types
* CHANGELOG.md
* Pass array operators down to fetch layer
* Read to first virtual row after seeking on a low definition level
This helps avoid additional spans/op in queries with only
resource attributes
---------
Co-authored-by: Martin Disibio <[email protected]>
156 lines
4.1 KiB
Go
156 lines
4.1 KiB
Go
package vparquet5
|
|
|
|
import (
|
|
"errors"
|
|
|
|
pq "github.com/grafana/tempo/pkg/parquetquery"
|
|
)
|
|
|
|
type rowNumberIterator struct {
|
|
rowNumbers []pq.RowNumber
|
|
}
|
|
|
|
var _ pq.Iterator = (*rowNumberIterator)(nil)
|
|
|
|
func (r *rowNumberIterator) String() string {
|
|
return "rowNumberIterator()"
|
|
}
|
|
|
|
func (r *rowNumberIterator) Next() (*pq.IteratorResult, error) {
|
|
if len(r.rowNumbers) == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
res := &pq.IteratorResult{RowNumber: r.rowNumbers[0]}
|
|
r.rowNumbers = r.rowNumbers[1:]
|
|
return res, nil
|
|
}
|
|
|
|
func (r *rowNumberIterator) SeekTo(to pq.RowNumber, definitionLevel int) (*pq.IteratorResult, error) {
|
|
var at *pq.IteratorResult
|
|
|
|
for at, _ = r.Next(); r != nil && at != nil && pq.CompareRowNumbers(definitionLevel, at.RowNumber, to) < 0; {
|
|
at, _ = r.Next()
|
|
}
|
|
|
|
return at, nil
|
|
}
|
|
|
|
func (r *rowNumberIterator) Close() {}
|
|
|
|
var _ pq.Iterator = (*virtualRowNumberIterator)(nil)
|
|
|
|
// virtualRowNumberIterator is an iterator that reads the row count from a column in a parquet file and uses this count
|
|
// to calculate virtual row numbers on the given definitionLevel. This is used to iterate over spans in a trace without
|
|
// actually reading a column on span definition level.
|
|
type virtualRowNumberIterator struct {
|
|
iter pq.Iterator // iterator returning the row count
|
|
definitionLevel int // definition level of virtual row numbers
|
|
|
|
at pq.IteratorResult
|
|
rowsMax int32
|
|
rowsLeft int32
|
|
}
|
|
|
|
// newVirtualRowNumberIterator creates a new virtual row number iterator. The iterator will read the row count from the
|
|
// given column and use it to calculate virtual row numbers on the given definitionLevel. The row number column read by iter
|
|
// is expected to have a definition level lower than definitionLevel.
|
|
func newVirtualRowNumberIterator(iter pq.Iterator, definitionLevel int) *virtualRowNumberIterator {
|
|
return &virtualRowNumberIterator{
|
|
iter: iter,
|
|
definitionLevel: definitionLevel,
|
|
at: pq.IteratorResult{RowNumber: pq.EmptyRowNumber()},
|
|
}
|
|
}
|
|
|
|
func (v *virtualRowNumberIterator) String() string {
|
|
return "virtualRowNumberIterator()"
|
|
}
|
|
|
|
func (v *virtualRowNumberIterator) Next() (*pq.IteratorResult, error) {
|
|
if v.rowsLeft == 0 {
|
|
res, err := v.iter.Next()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if res == nil {
|
|
return nil, nil
|
|
}
|
|
if len(res.Entries) != 1 {
|
|
return nil, errors.New("expecting exactly one entry")
|
|
}
|
|
|
|
v.at.RowNumber = res.RowNumber
|
|
v.setRows(res.Entries[0].Value.Int32())
|
|
|
|
if v.rowsLeft == 0 {
|
|
return &v.at, nil
|
|
}
|
|
}
|
|
|
|
v.rowsLeft--
|
|
v.at.RowNumber.Next(v.definitionLevel, v.definitionLevel, v.definitionLevel)
|
|
|
|
return &v.at, nil
|
|
}
|
|
|
|
func (v *virtualRowNumberIterator) SeekTo(rowNumber pq.RowNumber, definitionLevel int) (*pq.IteratorResult, error) {
|
|
// determine the definition level used for comparison of non-virtual row numbers (used for seeking in the row number column)
|
|
cmpLevel := min(definitionLevel, v.definitionLevel-1)
|
|
|
|
if pq.CompareRowNumbers(cmpLevel, rowNumber, v.at.RowNumber) != 0 {
|
|
res, err := v.iter.SeekTo(rowNumber, cmpLevel)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if res == nil {
|
|
return nil, nil
|
|
}
|
|
if len(res.Entries) != 1 {
|
|
return nil, errors.New("expecting exactly one entry")
|
|
}
|
|
|
|
v.at.RowNumber = res.RowNumber
|
|
v.setRows(res.Entries[0].Value.Int32())
|
|
|
|
if v.rowsLeft == 0 {
|
|
return &v.at, nil
|
|
}
|
|
} else {
|
|
v.at.RowNumber = pq.TruncateRowNumber(cmpLevel, rowNumber)
|
|
v.rowsLeft = v.rowsMax
|
|
}
|
|
|
|
var seek int32
|
|
if definitionLevel >= v.definitionLevel && rowNumber[v.definitionLevel] >= 0 {
|
|
seek = rowNumber[v.definitionLevel] + 1
|
|
}
|
|
if definitionLevel > v.definitionLevel && rowNumber[v.definitionLevel+1] >= 0 {
|
|
seek++
|
|
}
|
|
|
|
for seek > 0 && v.rowsLeft > 0 {
|
|
seek--
|
|
v.rowsLeft--
|
|
v.at.RowNumber.Next(v.definitionLevel, v.definitionLevel, v.definitionLevel)
|
|
}
|
|
|
|
rowsExhausted := v.rowsLeft == 0 && seek > 0
|
|
defLevelNotDefined := v.at.RowNumber[v.definitionLevel] < 0
|
|
if rowsExhausted || defLevelNotDefined {
|
|
return v.Next()
|
|
}
|
|
|
|
return &v.at, nil
|
|
}
|
|
|
|
func (v *virtualRowNumberIterator) Close() {
|
|
v.iter.Close()
|
|
v.setRows(0)
|
|
}
|
|
|
|
func (v *virtualRowNumberIterator) setRows(rows int32) {
|
|
v.rowsMax = rows
|
|
v.rowsLeft = rows
|
|
}
|