179 lines
4.0 KiB
Go
179 lines
4.0 KiB
Go
package query
|
|
|
|
import (
|
|
"io"
|
|
|
|
"github.com/influxdata/platform/query/iocounter"
|
|
"github.com/influxdata/platform/query/values"
|
|
)
|
|
|
|
type Result interface {
|
|
Name() string
|
|
// Tables returns a TableIterator for iterating through results
|
|
Tables() TableIterator
|
|
}
|
|
|
|
type TableIterator interface {
|
|
Do(f func(Table) error) error
|
|
}
|
|
|
|
type Table interface {
|
|
Key() GroupKey
|
|
|
|
Cols() []ColMeta
|
|
|
|
// Do calls f to process the data contained within the table.
|
|
// The function f will be called zero or more times.
|
|
Do(f func(ColReader) error) error
|
|
|
|
// RefCount modifies the reference count on the table by n.
|
|
// When the RefCount goes to zero, the table is freed.
|
|
RefCount(n int)
|
|
|
|
// Empty returns whether the table contains no records.
|
|
Empty() bool
|
|
}
|
|
|
|
type ColMeta struct {
|
|
Label string
|
|
Type DataType
|
|
}
|
|
|
|
type DataType int
|
|
|
|
const (
|
|
TInvalid DataType = iota
|
|
TBool
|
|
TInt
|
|
TUInt
|
|
TFloat
|
|
TString
|
|
TTime
|
|
)
|
|
|
|
func (t DataType) String() string {
|
|
switch t {
|
|
case TInvalid:
|
|
return "invalid"
|
|
case TBool:
|
|
return "bool"
|
|
case TInt:
|
|
return "int"
|
|
case TUInt:
|
|
return "uint"
|
|
case TFloat:
|
|
return "float"
|
|
case TString:
|
|
return "string"
|
|
case TTime:
|
|
return "time"
|
|
default:
|
|
return "unknown"
|
|
}
|
|
}
|
|
|
|
// ColReader allows access to reading slices of column data.
|
|
// All data the ColReader exposes is guaranteed to be in memory.
|
|
// Once a ColReader goes out of scope all slices are considered invalid.
|
|
type ColReader interface {
|
|
Key() GroupKey
|
|
// Cols returns a list of column metadata.
|
|
Cols() []ColMeta
|
|
// Len returns the length of the slices.
|
|
// All slices will have the same length.
|
|
Len() int
|
|
Bools(j int) []bool
|
|
Ints(j int) []int64
|
|
UInts(j int) []uint64
|
|
Floats(j int) []float64
|
|
Strings(j int) []string
|
|
Times(j int) []values.Time
|
|
}
|
|
|
|
type GroupKey interface {
|
|
Cols() []ColMeta
|
|
|
|
HasCol(label string) bool
|
|
|
|
ValueBool(j int) bool
|
|
ValueUInt(j int) uint64
|
|
ValueInt(j int) int64
|
|
ValueFloat(j int) float64
|
|
ValueString(j int) string
|
|
ValueDuration(j int) values.Duration
|
|
ValueTime(j int) values.Time
|
|
Value(j int) values.Value
|
|
|
|
Equal(o GroupKey) bool
|
|
Less(o GroupKey) bool
|
|
String() string
|
|
}
|
|
|
|
// ResultDecoder can decode a result from a reader.
|
|
type ResultDecoder interface {
|
|
// Decode decodes data from r into a result.
|
|
Decode(r io.Reader) (Result, error)
|
|
}
|
|
|
|
// ResultEncoder can encode a result into a writer.
|
|
type ResultEncoder interface {
|
|
// Encode encodes data from the result into w.
|
|
// Returns the number of bytes written to w and any error.
|
|
Encode(w io.Writer, result Result) (int64, error)
|
|
}
|
|
|
|
// MultiResultDecoder can decode multiple results from a reader.
|
|
type MultiResultDecoder interface {
|
|
// Decode decodes multiple results from r.
|
|
Decode(r io.ReadCloser) (ResultIterator, error)
|
|
}
|
|
|
|
// MultiResultEncoder can encode multiple results into a writer.
|
|
type MultiResultEncoder interface {
|
|
// Encode writes multiple results from r into w.
|
|
// Returns the number of bytes written to w and any error.
|
|
Encode(w io.Writer, results ResultIterator) (int64, error)
|
|
}
|
|
|
|
// DelimitedMultiResultEncoder encodes multiple results using a trailing delimiter.
|
|
// The delimiter is written after every result.
|
|
//
|
|
// If an error is encountered when iterating EncodeError will be called on the Encoder.
|
|
//
|
|
// If the io.Writer implements flusher, it will be flushed after each delimiter.
|
|
type DelimitedMultiResultEncoder struct {
|
|
Delimiter []byte
|
|
Encoder interface {
|
|
ResultEncoder
|
|
// EncodeError encodes an error on the writer.
|
|
EncodeError(w io.Writer, err error) error
|
|
}
|
|
}
|
|
|
|
type flusher interface {
|
|
Flush()
|
|
}
|
|
|
|
func (e *DelimitedMultiResultEncoder) Encode(w io.Writer, results ResultIterator) (int64, error) {
|
|
wc := &iocounter.Writer{Writer: w}
|
|
for results.More() {
|
|
result := results.Next()
|
|
if _, err := e.Encoder.Encode(wc, result); err != nil {
|
|
return wc.Count(), err
|
|
}
|
|
if _, err := wc.Write(e.Delimiter); err != nil {
|
|
return wc.Count(), err
|
|
}
|
|
// Flush the writer after each result
|
|
if f, ok := w.(flusher); ok {
|
|
f.Flush()
|
|
}
|
|
}
|
|
err := results.Err()
|
|
if err != nil {
|
|
err := e.Encoder.EncodeError(wc, err)
|
|
return wc.Count(), err
|
|
}
|
|
return wc.Count(), nil
|
|
}
|