package query import ( "encoding/base64" "io" "sort" "strconv" "strings" "time" "github.com/influxdata/influx-cli/v2/pkg/fluxcsv" ) // formattingPrinter formats query results into a structured table before printing. type formattingPrinter struct { widths []int maxWidth int newWidths []int pad []byte dash []byte // fmtBuf is used to format values fmtBuf [64]byte cols []fluxcsv.FluxColumn lastColIdx int } func NewFormattingPrinter() *formattingPrinter { return &formattingPrinter{} } func (f *formattingPrinter) PrintQueryResults(resultStream io.ReadCloser, out io.Writer) error { res := fluxcsv.NewQueryTableResult(resultStream) defer res.Close() return f.write(res, out) } const fixedWidthTimeFmt = "2006-01-02T15:04:05.000000000Z" var eol = []byte{'\n'} type writeHelper struct { w io.Writer err error } func (w *writeHelper) write(data []byte) { if w.err != nil { return } _, err := w.w.Write(data) w.err = err } var minWidthsByType = map[fluxcsv.ColType]int{ fluxcsv.BoolDatatype: 12, fluxcsv.LongDatatype: 26, fluxcsv.ULongDatatype: 27, fluxcsv.DoubleDatatype: 28, fluxcsv.StringDatatype: 22, fluxcsv.TimeDatatypeRFC: len(fixedWidthTimeFmt), fluxcsv.TimeDatatypeRFCNano: len(fixedWidthTimeFmt), fluxcsv.Base64BinaryDataType: 22, fluxcsv.DurationDatatype: 22, } // write writes the formatted table data to w. func (f *formattingPrinter) write(res *fluxcsv.QueryTableResult, out io.Writer) error { w := &writeHelper{w: out} r := 0 for res.Next() { record := res.Record() if res.AnnotationsChanged() { // Reset and sort cols f.cols = res.Metadata().Columns() f.lastColIdx = len(f.cols) - 1 groupKeys := make(map[string]int, len(res.Metadata().GroupKeyCols())) for i, k := range res.Metadata().GroupKeyCols() { groupKeys[k] = i } sort.Slice(f.cols, func(i, j int) bool { iCol, jCol := f.cols[i], f.cols[j] iGroupIdx, iIsGroup := groupKeys[iCol.Name()] jGroupIdx, jIsGroup := groupKeys[jCol.Name()] if iIsGroup && jIsGroup { return iGroupIdx < jGroupIdx } if !iIsGroup && !jIsGroup { return i < j } return iIsGroup && !jIsGroup }) // Compute header widths f.widths = make([]int, len(f.cols)) for i, c := range f.cols { // Column header is "