220 lines
3.9 KiB
Go
220 lines
3.9 KiB
Go
package reads_test
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"strings"
|
|
|
|
"github.com/influxdata/influxdb/v2/models"
|
|
"github.com/influxdata/influxdb/v2/storage/reads"
|
|
"github.com/influxdata/influxdb/v2/tsdb/cursors"
|
|
)
|
|
|
|
func cursorToString(wr io.Writer, cur cursors.Cursor) {
|
|
switch ccur := cur.(type) {
|
|
case cursors.IntegerArrayCursor:
|
|
fmt.Fprintln(wr, "Integer")
|
|
for {
|
|
a := ccur.Next()
|
|
if a.Len() > 0 {
|
|
for i := range a.Timestamps {
|
|
fmt.Fprintf(wr, "%20d | %20d\n", a.Timestamps[i], a.Values[i])
|
|
}
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
case cursors.FloatArrayCursor:
|
|
fmt.Fprintln(wr, "Float")
|
|
for {
|
|
a := ccur.Next()
|
|
if a.Len() > 0 {
|
|
for i := range a.Timestamps {
|
|
fmt.Fprintf(wr, "%20d | %18.2f\n", a.Timestamps[i], a.Values[i])
|
|
}
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
case cursors.UnsignedArrayCursor:
|
|
fmt.Fprintln(wr, "Unsigned")
|
|
for {
|
|
a := ccur.Next()
|
|
if a.Len() > 0 {
|
|
for i := range a.Timestamps {
|
|
fmt.Fprintf(wr, "%20d | %20d\n", a.Timestamps[i], a.Values[i])
|
|
}
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
case cursors.BooleanArrayCursor:
|
|
fmt.Fprintln(wr, "Boolean")
|
|
for {
|
|
a := ccur.Next()
|
|
if a.Len() > 0 {
|
|
for i := range a.Timestamps {
|
|
fmt.Fprintf(wr, "%20d | %t\n", a.Timestamps[i], a.Values[i])
|
|
}
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
case cursors.StringArrayCursor:
|
|
fmt.Fprintln(wr, "String")
|
|
for {
|
|
a := ccur.Next()
|
|
if a.Len() > 0 {
|
|
for i := range a.Timestamps {
|
|
fmt.Fprintf(wr, "%20d | %20s\n", a.Timestamps[i], a.Values[i])
|
|
}
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
default:
|
|
fmt.Fprintln(wr, "Invalid")
|
|
fmt.Fprintf(wr, "unreachable: %T\n", cur)
|
|
}
|
|
|
|
if err := cur.Err(); err != nil && err != io.EOF {
|
|
fmt.Fprintf(wr, "cursor err: %s\n", cur.Err().Error())
|
|
}
|
|
|
|
cur.Close()
|
|
}
|
|
|
|
const nilVal = "<nil>"
|
|
|
|
func joinString(b [][]byte) string {
|
|
s := make([]string, len(b))
|
|
for i := range b {
|
|
v := b[i]
|
|
if len(v) == 0 {
|
|
s[i] = nilVal
|
|
} else {
|
|
s[i] = string(v)
|
|
}
|
|
}
|
|
return strings.Join(s, ",")
|
|
}
|
|
|
|
func tagsToString(wr io.Writer, tags models.Tags, opts ...optionFn) {
|
|
if k := tags.HashKey(); len(k) > 0 {
|
|
fmt.Fprintf(wr, "%s", string(k[1:]))
|
|
}
|
|
fmt.Fprintln(wr)
|
|
}
|
|
|
|
func resultSetToString(wr io.Writer, rs reads.ResultSet, opts ...optionFn) {
|
|
var po PrintOptions
|
|
for _, o := range opts {
|
|
o(&po)
|
|
}
|
|
|
|
iw := ensureIndentWriter(wr)
|
|
wr = iw
|
|
|
|
for rs.Next() {
|
|
fmt.Fprint(wr, "series: ")
|
|
tagsToString(wr, rs.Tags())
|
|
cur := rs.Cursor()
|
|
|
|
if po.SkipNilCursor && cur == nil {
|
|
continue
|
|
}
|
|
|
|
iw.Indent(2)
|
|
|
|
fmt.Fprint(wr, "cursor:")
|
|
if cur == nil {
|
|
fmt.Fprintln(wr, nilVal)
|
|
goto LOOP
|
|
}
|
|
|
|
cursorToString(wr, cur)
|
|
LOOP:
|
|
iw.Indent(-2)
|
|
}
|
|
}
|
|
|
|
func GroupResultSetToString(wr io.Writer, rs reads.GroupResultSet, opts ...optionFn) {
|
|
iw := ensureIndentWriter(wr)
|
|
wr = iw
|
|
|
|
gc := rs.Next()
|
|
for gc != nil {
|
|
fmt.Fprintln(wr, "group:")
|
|
iw.Indent(2)
|
|
fmt.Fprintf(wr, "tag key : %s\n", joinString(gc.Keys()))
|
|
fmt.Fprintf(wr, "partition key: %s\n", joinString(gc.PartitionKeyVals()))
|
|
iw.Indent(2)
|
|
resultSetToString(wr, gc, opts...)
|
|
iw.Indent(-4)
|
|
gc = rs.Next()
|
|
}
|
|
}
|
|
|
|
type PrintOptions struct {
|
|
SkipNilCursor bool
|
|
}
|
|
|
|
type optionFn func(o *PrintOptions)
|
|
|
|
func SkipNilCursor() optionFn {
|
|
return func(o *PrintOptions) {
|
|
o.SkipNilCursor = true
|
|
}
|
|
}
|
|
|
|
type indentWriter struct {
|
|
l int
|
|
p []byte
|
|
wr io.Writer
|
|
bol bool
|
|
}
|
|
|
|
func ensureIndentWriter(wr io.Writer) *indentWriter {
|
|
if iw, ok := wr.(*indentWriter); ok {
|
|
return iw
|
|
} else {
|
|
return newIndentWriter(wr)
|
|
}
|
|
}
|
|
|
|
func newIndentWriter(wr io.Writer) *indentWriter {
|
|
return &indentWriter{
|
|
wr: wr,
|
|
bol: true,
|
|
}
|
|
}
|
|
|
|
func (w *indentWriter) Indent(n int) {
|
|
w.l += n
|
|
if w.l < 0 {
|
|
panic("negative indent")
|
|
}
|
|
w.p = bytes.Repeat([]byte(" "), w.l)
|
|
}
|
|
|
|
func (w *indentWriter) Write(p []byte) (n int, err error) {
|
|
for _, c := range p {
|
|
if w.bol {
|
|
_, err = w.wr.Write(w.p)
|
|
if err != nil {
|
|
break
|
|
}
|
|
w.bol = false
|
|
}
|
|
_, err = w.wr.Write([]byte{c})
|
|
if err != nil {
|
|
break
|
|
}
|
|
n++
|
|
w.bol = c == '\n'
|
|
}
|
|
|
|
return n, err
|
|
}
|