From 733a17d9e9e148a7b54feb9ce40246a141071737 Mon Sep 17 00:00:00 2001 From: "Jonathan A. Sternberg" Date: Tue, 10 May 2016 13:16:55 -0400 Subject: [PATCH] Update SHOW FIELD KEYS to return the field type with the field key Fixes #3451. --- CHANGELOG.md | 6 +++ cmd/influxd/run/server_test.go | 6 +-- influxql/statement_rewriter.go | 1 + influxql/statement_rewriter_test.go | 10 ++-- tsdb/shard.go | 74 +++++++++++++++++++++++++++-- 5 files changed, 84 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index affe2fae093..42029e3e689 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## v1.0.0 [unreleased] + +### Features + +- [#3541](https://github.com/influxdata/influxdb/issues/3451): Update SHOW FIELD KEYS to return the field type with the field key. + ## v0.13.0 [unreleased] ### Release Notes diff --git a/cmd/influxd/run/server_test.go b/cmd/influxd/run/server_test.go index 830f6f132b0..108e1aed13c 100644 --- a/cmd/influxd/run/server_test.go +++ b/cmd/influxd/run/server_test.go @@ -5568,19 +5568,19 @@ func TestServer_Query_ShowFieldKeys(t *testing.T) { &Query{ name: `show field keys`, command: `SHOW FIELD KEYS`, - exp: `{"results":[{"series":[{"name":"cpu","columns":["fieldKey"],"values":[["field1"],["field2"],["field3"]]},{"name":"disk","columns":["fieldKey"],"values":[["field8"],["field9"]]},{"name":"gpu","columns":["fieldKey"],"values":[["field4"],["field5"],["field6"],["field7"]]}]}]}`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["fieldKey","fieldType"],"values":[["field1","float"],["field2","float"],["field3","float"]]},{"name":"disk","columns":["fieldKey","fieldType"],"values":[["field8","float"],["field9","float"]]},{"name":"gpu","columns":["fieldKey","fieldType"],"values":[["field4","float"],["field5","float"],["field6","float"],["field7","float"]]}]}]}`, params: url.Values{"db": []string{"db0"}}, }, &Query{ name: `show field keys from measurement`, command: `SHOW FIELD KEYS FROM cpu`, - exp: `{"results":[{"series":[{"name":"cpu","columns":["fieldKey"],"values":[["field1"],["field2"],["field3"]]}]}]}`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["fieldKey","fieldType"],"values":[["field1","float"],["field2","float"],["field3","float"]]}]}]}`, params: url.Values{"db": []string{"db0"}}, }, &Query{ name: `show field keys measurement with regex`, command: `SHOW FIELD KEYS FROM /[cg]pu/`, - exp: `{"results":[{"series":[{"name":"cpu","columns":["fieldKey"],"values":[["field1"],["field2"],["field3"]]},{"name":"gpu","columns":["fieldKey"],"values":[["field4"],["field5"],["field6"],["field7"]]}]}]}`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["fieldKey","fieldType"],"values":[["field1","float"],["field2","float"],["field3","float"]]},{"name":"gpu","columns":["fieldKey","fieldType"],"values":[["field4","float"],["field5","float"],["field6","float"],["field7","float"]]}]}]}`, params: url.Values{"db": []string{"db0"}}, }, }...) diff --git a/influxql/statement_rewriter.go b/influxql/statement_rewriter.go index 0d0549d3aaf..84927d540c9 100644 --- a/influxql/statement_rewriter.go +++ b/influxql/statement_rewriter.go @@ -24,6 +24,7 @@ func rewriteShowFieldKeysStatement(stmt *ShowFieldKeysStatement) (Statement, err return &SelectStatement{ Fields: Fields([]*Field{ {Expr: &VarRef{Val: "fieldKey"}}, + {Expr: &VarRef{Val: "fieldType"}}, }), Sources: rewriteSources(stmt.Sources, "_fieldKeys"), Condition: rewriteSourcesCondition(stmt.Sources, nil), diff --git a/influxql/statement_rewriter_test.go b/influxql/statement_rewriter_test.go index 85b7ad543fd..7251f0ff6b8 100644 --- a/influxql/statement_rewriter_test.go +++ b/influxql/statement_rewriter_test.go @@ -13,23 +13,23 @@ func TestRewriteStatement(t *testing.T) { }{ { stmt: `SHOW FIELD KEYS`, - s: `SELECT fieldKey FROM _fieldKeys`, + s: `SELECT fieldKey, fieldType FROM _fieldKeys`, }, { stmt: `SHOW FIELD KEYS FROM cpu`, - s: `SELECT fieldKey FROM _fieldKeys WHERE _name = 'cpu'`, + s: `SELECT fieldKey, fieldType FROM _fieldKeys WHERE _name = 'cpu'`, }, { stmt: `SHOW FIELD KEYS FROM /c.*/`, - s: `SELECT fieldKey FROM _fieldKeys WHERE _name =~ /c.*/`, + s: `SELECT fieldKey, fieldType FROM _fieldKeys WHERE _name =~ /c.*/`, }, { stmt: `SHOW FIELD KEYS FROM mydb.myrp2.cpu`, - s: `SELECT fieldKey FROM mydb.myrp2._fieldKeys WHERE _name = 'cpu'`, + s: `SELECT fieldKey, fieldType FROM mydb.myrp2._fieldKeys WHERE _name = 'cpu'`, }, { stmt: `SHOW FIELD KEYS FROM mydb.myrp2./c.*/`, - s: `SELECT fieldKey FROM mydb.myrp2._fieldKeys WHERE _name =~ /c.*/`, + s: `SELECT fieldKey, fieldType FROM mydb.myrp2._fieldKeys WHERE _name =~ /c.*/`, }, { stmt: `SHOW MEASUREMENTS`, diff --git a/tsdb/shard.go b/tsdb/shard.go index 308613e1c15..7e6ecc8e231 100644 --- a/tsdb/shard.go +++ b/tsdb/shard.go @@ -944,12 +944,76 @@ func (ic *shardIteratorCreator) ExpandSources(sources influxql.Sources) (influxq } func NewFieldKeysIterator(sh *Shard, opt influxql.IteratorOptions) (influxql.Iterator, error) { - fn := func(m *Measurement) []string { - keys := m.FieldNames() - sort.Strings(keys) - return keys + itr := &fieldKeysIterator{sh: sh} + + // Retrieve measurements from shard. Filter if condition specified. + if opt.Condition == nil { + itr.mms = sh.index.Measurements() + } else { + mms, _, err := sh.index.measurementsByExpr(opt.Condition) + if err != nil { + return nil, err + } + itr.mms = mms + } + + // Sort measurements by name. + sort.Sort(itr.mms) + + return itr, nil +} + +// fieldKeysIterator iterates over measurements and gets field keys from each measurement. +type fieldKeysIterator struct { + sh *Shard + mms Measurements // remaining measurements + buf struct { + mm *Measurement // current measurement + fields []*Field // current measurement's fields + } +} + +// Stats returns stats about the points processed. +func (itr *fieldKeysIterator) Stats() influxql.IteratorStats { return influxql.IteratorStats{} } + +// Close closes the iterator. +func (itr *fieldKeysIterator) Close() error { return nil } + +// Next emits the next tag key name. +func (itr *fieldKeysIterator) Next() (*influxql.FloatPoint, error) { + for { + // If there are no more keys then move to the next measurements. + if len(itr.buf.fields) == 0 { + if len(itr.mms) == 0 { + return nil, nil + } + + itr.buf.mm = itr.mms[0] + keys := itr.buf.mm.FieldNames() + if len(keys) > 0 { + // Sort the keys in alphabetical order. + sort.Strings(keys) + // Retrieve the field for each key. + mf := itr.sh.engine.MeasurementFields(itr.buf.mm.Name) + itr.buf.fields = make([]*Field, len(keys)) + for i, name := range keys { + itr.buf.fields[i] = mf.Field(name) + } + } + itr.mms = itr.mms[1:] + continue + } + + // Return next key. + field := itr.buf.fields[0] + p := &influxql.FloatPoint{ + Name: itr.buf.mm.Name, + Aux: []interface{}{field.Name, field.Type.String()}, + } + itr.buf.fields = itr.buf.fields[1:] + + return p, nil } - return newMeasurementKeysIterator(sh, fn, opt) } // MeasurementIterator represents a string iterator that emits all measurement names in a shard.