327 lines
8.6 KiB
Go
327 lines
8.6 KiB
Go
package execute
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/influxdata/platform/query"
|
|
)
|
|
|
|
type selectorTransformation struct {
|
|
d Dataset
|
|
cache BlockBuilderCache
|
|
|
|
config SelectorConfig
|
|
}
|
|
|
|
type SelectorConfig struct {
|
|
Column string `json:"column"`
|
|
}
|
|
|
|
func (c *SelectorConfig) ReadArgs(args query.Arguments) error {
|
|
if col, ok, err := args.GetString("column"); err != nil {
|
|
return err
|
|
} else if ok {
|
|
c.Column = col
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type rowSelectorTransformation struct {
|
|
selectorTransformation
|
|
selector RowSelector
|
|
}
|
|
type indexSelectorTransformation struct {
|
|
selectorTransformation
|
|
selector IndexSelector
|
|
}
|
|
|
|
func NewRowSelectorTransformationAndDataset(id DatasetID, mode AccumulationMode, selector RowSelector, config SelectorConfig, a *Allocator) (*rowSelectorTransformation, Dataset) {
|
|
cache := NewBlockBuilderCache(a)
|
|
d := NewDataset(id, mode, cache)
|
|
return NewRowSelectorTransformation(d, cache, selector, config), d
|
|
}
|
|
func NewRowSelectorTransformation(d Dataset, c BlockBuilderCache, selector RowSelector, config SelectorConfig) *rowSelectorTransformation {
|
|
return &rowSelectorTransformation{
|
|
selectorTransformation: newSelectorTransformation(d, c, config),
|
|
selector: selector,
|
|
}
|
|
}
|
|
|
|
func NewIndexSelectorTransformationAndDataset(id DatasetID, mode AccumulationMode, selector IndexSelector, config SelectorConfig, a *Allocator) (*indexSelectorTransformation, Dataset) {
|
|
cache := NewBlockBuilderCache(a)
|
|
d := NewDataset(id, mode, cache)
|
|
return NewIndexSelectorTransformation(d, cache, selector, config), d
|
|
}
|
|
func NewIndexSelectorTransformation(d Dataset, c BlockBuilderCache, selector IndexSelector, config SelectorConfig) *indexSelectorTransformation {
|
|
return &indexSelectorTransformation{
|
|
selectorTransformation: newSelectorTransformation(d, c, config),
|
|
selector: selector,
|
|
}
|
|
}
|
|
|
|
func newSelectorTransformation(d Dataset, c BlockBuilderCache, config SelectorConfig) selectorTransformation {
|
|
if config.Column == "" {
|
|
config.Column = DefaultValueColLabel
|
|
}
|
|
return selectorTransformation{
|
|
d: d,
|
|
cache: c,
|
|
config: config,
|
|
}
|
|
}
|
|
|
|
func (t *selectorTransformation) RetractBlock(id DatasetID, key query.PartitionKey) error {
|
|
//TODO(nathanielc): Store intermediate state for retractions
|
|
return t.d.RetractBlock(key)
|
|
}
|
|
func (t *selectorTransformation) UpdateWatermark(id DatasetID, mark Time) error {
|
|
return t.d.UpdateWatermark(mark)
|
|
}
|
|
func (t *selectorTransformation) UpdateProcessingTime(id DatasetID, pt Time) error {
|
|
return t.d.UpdateProcessingTime(pt)
|
|
}
|
|
func (t *selectorTransformation) Finish(id DatasetID, err error) {
|
|
t.d.Finish(err)
|
|
}
|
|
|
|
func (t *selectorTransformation) setupBuilder(b query.Block) (BlockBuilder, int, error) {
|
|
builder, new := t.cache.BlockBuilder(b.Key())
|
|
if !new {
|
|
return nil, 0, fmt.Errorf("found duplicate block with key: %v", b.Key())
|
|
}
|
|
AddBlockCols(b, builder)
|
|
|
|
cols := builder.Cols()
|
|
valueIdx := ColIdx(t.config.Column, cols)
|
|
if valueIdx < 0 {
|
|
return nil, 0, fmt.Errorf("no column %q exists", t.config.Column)
|
|
}
|
|
return builder, valueIdx, nil
|
|
}
|
|
|
|
func (t *indexSelectorTransformation) Process(id DatasetID, b query.Block) error {
|
|
builder, valueIdx, err := t.setupBuilder(b)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
valueCol := builder.Cols()[valueIdx]
|
|
|
|
var s interface{}
|
|
switch valueCol.Type {
|
|
case query.TBool:
|
|
s = t.selector.NewBoolSelector()
|
|
case query.TInt:
|
|
s = t.selector.NewIntSelector()
|
|
case query.TUInt:
|
|
s = t.selector.NewUIntSelector()
|
|
case query.TFloat:
|
|
s = t.selector.NewFloatSelector()
|
|
case query.TString:
|
|
s = t.selector.NewStringSelector()
|
|
default:
|
|
return fmt.Errorf("unsupported selector type %v", valueCol.Type)
|
|
}
|
|
|
|
return b.Do(func(cr query.ColReader) error {
|
|
switch valueCol.Type {
|
|
case query.TBool:
|
|
selected := s.(DoBoolIndexSelector).DoBool(cr.Bools(valueIdx))
|
|
t.appendSelected(selected, builder, cr)
|
|
case query.TInt:
|
|
selected := s.(DoIntIndexSelector).DoInt(cr.Ints(valueIdx))
|
|
t.appendSelected(selected, builder, cr)
|
|
case query.TUInt:
|
|
selected := s.(DoUIntIndexSelector).DoUInt(cr.UInts(valueIdx))
|
|
t.appendSelected(selected, builder, cr)
|
|
case query.TFloat:
|
|
selected := s.(DoFloatIndexSelector).DoFloat(cr.Floats(valueIdx))
|
|
t.appendSelected(selected, builder, cr)
|
|
case query.TString:
|
|
selected := s.(DoStringIndexSelector).DoString(cr.Strings(valueIdx))
|
|
t.appendSelected(selected, builder, cr)
|
|
default:
|
|
return fmt.Errorf("unsupported selector type %v", valueCol.Type)
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func (t *rowSelectorTransformation) Process(id DatasetID, b query.Block) error {
|
|
builder, valueIdx, err := t.setupBuilder(b)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
valueCol := builder.Cols()[valueIdx]
|
|
|
|
var rower Rower
|
|
switch valueCol.Type {
|
|
case query.TBool:
|
|
rower = t.selector.NewBoolSelector()
|
|
case query.TInt:
|
|
rower = t.selector.NewIntSelector()
|
|
case query.TUInt:
|
|
rower = t.selector.NewUIntSelector()
|
|
case query.TFloat:
|
|
rower = t.selector.NewFloatSelector()
|
|
case query.TString:
|
|
rower = t.selector.NewStringSelector()
|
|
default:
|
|
return fmt.Errorf("unsupported selector type %v", valueCol.Type)
|
|
}
|
|
|
|
b.Do(func(cr query.ColReader) error {
|
|
switch valueCol.Type {
|
|
case query.TBool:
|
|
rower.(DoBoolRowSelector).DoBool(cr.Bools(valueIdx), cr)
|
|
case query.TInt:
|
|
rower.(DoIntRowSelector).DoInt(cr.Ints(valueIdx), cr)
|
|
case query.TUInt:
|
|
rower.(DoUIntRowSelector).DoUInt(cr.UInts(valueIdx), cr)
|
|
case query.TFloat:
|
|
rower.(DoFloatRowSelector).DoFloat(cr.Floats(valueIdx), cr)
|
|
case query.TString:
|
|
rower.(DoStringRowSelector).DoString(cr.Strings(valueIdx), cr)
|
|
default:
|
|
return fmt.Errorf("unsupported selector type %v", valueCol.Type)
|
|
}
|
|
return nil
|
|
})
|
|
rows := rower.Rows()
|
|
t.appendRows(builder, rows)
|
|
return nil
|
|
}
|
|
|
|
func (t *indexSelectorTransformation) appendSelected(selected []int, builder BlockBuilder, cr query.ColReader) {
|
|
if len(selected) == 0 {
|
|
return
|
|
}
|
|
cols := builder.Cols()
|
|
for j, c := range cols {
|
|
for _, i := range selected {
|
|
switch c.Type {
|
|
case query.TBool:
|
|
builder.AppendBool(j, cr.Bools(j)[i])
|
|
case query.TInt:
|
|
builder.AppendInt(j, cr.Ints(j)[i])
|
|
case query.TUInt:
|
|
builder.AppendUInt(j, cr.UInts(j)[i])
|
|
case query.TFloat:
|
|
builder.AppendFloat(j, cr.Floats(j)[i])
|
|
case query.TString:
|
|
builder.AppendString(j, cr.Strings(j)[i])
|
|
case query.TTime:
|
|
builder.AppendTime(j, cr.Times(j)[i])
|
|
default:
|
|
PanicUnknownType(c.Type)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (t *rowSelectorTransformation) appendRows(builder BlockBuilder, rows []Row) {
|
|
cols := builder.Cols()
|
|
for j, c := range cols {
|
|
for _, row := range rows {
|
|
v := row.Values[j]
|
|
switch c.Type {
|
|
case query.TBool:
|
|
builder.AppendBool(j, v.(bool))
|
|
case query.TInt:
|
|
builder.AppendInt(j, v.(int64))
|
|
case query.TUInt:
|
|
builder.AppendUInt(j, v.(uint64))
|
|
case query.TFloat:
|
|
builder.AppendFloat(j, v.(float64))
|
|
case query.TString:
|
|
builder.AppendString(j, v.(string))
|
|
case query.TTime:
|
|
builder.AppendTime(j, v.(Time))
|
|
default:
|
|
PanicUnknownType(c.Type)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
type IndexSelector interface {
|
|
NewBoolSelector() DoBoolIndexSelector
|
|
NewIntSelector() DoIntIndexSelector
|
|
NewUIntSelector() DoUIntIndexSelector
|
|
NewFloatSelector() DoFloatIndexSelector
|
|
NewStringSelector() DoStringIndexSelector
|
|
}
|
|
type DoBoolIndexSelector interface {
|
|
DoBool([]bool) []int
|
|
}
|
|
type DoIntIndexSelector interface {
|
|
DoInt([]int64) []int
|
|
}
|
|
type DoUIntIndexSelector interface {
|
|
DoUInt([]uint64) []int
|
|
}
|
|
type DoFloatIndexSelector interface {
|
|
DoFloat([]float64) []int
|
|
}
|
|
type DoStringIndexSelector interface {
|
|
DoString([]string) []int
|
|
}
|
|
|
|
type RowSelector interface {
|
|
NewBoolSelector() DoBoolRowSelector
|
|
NewIntSelector() DoIntRowSelector
|
|
NewUIntSelector() DoUIntRowSelector
|
|
NewFloatSelector() DoFloatRowSelector
|
|
NewStringSelector() DoStringRowSelector
|
|
}
|
|
|
|
type Rower interface {
|
|
Rows() []Row
|
|
}
|
|
|
|
type DoBoolRowSelector interface {
|
|
Rower
|
|
DoBool(vs []bool, cr query.ColReader)
|
|
}
|
|
type DoIntRowSelector interface {
|
|
Rower
|
|
DoInt(vs []int64, cr query.ColReader)
|
|
}
|
|
type DoUIntRowSelector interface {
|
|
Rower
|
|
DoUInt(vs []uint64, cr query.ColReader)
|
|
}
|
|
type DoFloatRowSelector interface {
|
|
Rower
|
|
DoFloat(vs []float64, cr query.ColReader)
|
|
}
|
|
type DoStringRowSelector interface {
|
|
Rower
|
|
DoString(vs []string, cr query.ColReader)
|
|
}
|
|
|
|
type Row struct {
|
|
Values []interface{}
|
|
}
|
|
|
|
func ReadRow(i int, cr query.ColReader) (row Row) {
|
|
cols := cr.Cols()
|
|
row.Values = make([]interface{}, len(cols))
|
|
for j, c := range cols {
|
|
switch c.Type {
|
|
case query.TBool:
|
|
row.Values[j] = cr.Bools(j)[i]
|
|
case query.TInt:
|
|
row.Values[j] = cr.Ints(j)[i]
|
|
case query.TUInt:
|
|
row.Values[j] = cr.UInts(j)[i]
|
|
case query.TFloat:
|
|
row.Values[j] = cr.Floats(j)[i]
|
|
case query.TString:
|
|
row.Values[j] = cr.Strings(j)[i]
|
|
case query.TTime:
|
|
row.Values[j] = cr.Times(j)[i]
|
|
}
|
|
}
|
|
return
|
|
}
|