Remove unused functions in influxql/ast.go
parent
905e7fe05e
commit
ef0ad3292d
261
influxql/ast.go
261
influxql/ast.go
|
@ -81,15 +81,6 @@ func InspectDataType(v interface{}) DataType {
|
|||
}
|
||||
}
|
||||
|
||||
// InspectDataTypes returns all of the data types for an interface slice.
|
||||
func InspectDataTypes(a []interface{}) []DataType {
|
||||
dta := make([]DataType, len(a))
|
||||
for i, v := range a {
|
||||
dta[i] = InspectDataType(v)
|
||||
}
|
||||
return dta
|
||||
}
|
||||
|
||||
// LessThan returns true if the other DataType has greater precedence than the
|
||||
// current data type. Unknown has the lowest precedence.
|
||||
//
|
||||
|
@ -361,61 +352,6 @@ func (*SubQuery) source() {}
|
|||
// Sources represents a list of sources.
|
||||
type Sources []Source
|
||||
|
||||
// Names returns a list of source names.
|
||||
func (a Sources) Names() []string {
|
||||
names := make([]string, 0, len(a))
|
||||
for _, s := range a {
|
||||
switch s := s.(type) {
|
||||
case *Measurement:
|
||||
names = append(names, s.Name)
|
||||
}
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
// Filter returns a list of source names filtered by the database/retention policy.
|
||||
func (a Sources) Filter(database, retentionPolicy string) []Source {
|
||||
sources := make([]Source, 0, len(a))
|
||||
for _, s := range a {
|
||||
switch s := s.(type) {
|
||||
case *Measurement:
|
||||
if s.Database == database && s.RetentionPolicy == retentionPolicy {
|
||||
sources = append(sources, s)
|
||||
}
|
||||
case *SubQuery:
|
||||
filteredSources := s.Statement.Sources.Filter(database, retentionPolicy)
|
||||
sources = append(sources, filteredSources...)
|
||||
}
|
||||
}
|
||||
return sources
|
||||
}
|
||||
|
||||
// HasSystemSource returns true if any of the sources are internal, system sources.
|
||||
func (a Sources) HasSystemSource() bool {
|
||||
for _, s := range a {
|
||||
switch s := s.(type) {
|
||||
case *Measurement:
|
||||
if IsSystemName(s.Name) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// HasRegex returns true if any of the sources are regex measurements.
|
||||
func (a Sources) HasRegex() bool {
|
||||
for _, s := range a {
|
||||
switch s := s.(type) {
|
||||
case *Measurement:
|
||||
if s.Regex != nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// String returns a string representation of a Sources array.
|
||||
func (a Sources) String() string {
|
||||
var buf bytes.Buffer
|
||||
|
@ -1070,46 +1006,6 @@ type SelectStatement struct {
|
|||
Dedupe bool
|
||||
}
|
||||
|
||||
// HasDerivative returns true if any function call in the statement is a
|
||||
// derivative aggregate.
|
||||
func (s *SelectStatement) HasDerivative() bool {
|
||||
for _, f := range s.FunctionCalls() {
|
||||
if f.Name == "derivative" || f.Name == "non_negative_derivative" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsSimpleDerivative return true if any function call is a derivative function with a
|
||||
// variable ref as the first arg.
|
||||
func (s *SelectStatement) IsSimpleDerivative() bool {
|
||||
for _, f := range s.FunctionCalls() {
|
||||
if f.Name == "derivative" || f.Name == "non_negative_derivative" {
|
||||
// it's nested if the first argument is an aggregate function
|
||||
if _, ok := f.Args[0].(*VarRef); ok {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// HasSelector returns true if there is exactly one selector.
|
||||
func (s *SelectStatement) HasSelector() bool {
|
||||
var selector *Call
|
||||
for _, f := range s.Fields {
|
||||
if call, ok := f.Expr.(*Call); ok {
|
||||
if selector != nil || !IsSelector(call) {
|
||||
// This is an aggregate call or there is already a selector.
|
||||
return false
|
||||
}
|
||||
selector = call
|
||||
}
|
||||
}
|
||||
return selector != nil
|
||||
}
|
||||
|
||||
// TimeAscending returns true if the time field is sorted in chronological order.
|
||||
func (s *SelectStatement) TimeAscending() bool {
|
||||
return len(s.SortFields) == 0 || s.SortFields[0].Ascending
|
||||
|
@ -1529,42 +1425,6 @@ func (s *SelectStatement) RewriteTimeFields() {
|
|||
}
|
||||
}
|
||||
|
||||
// RewriteTimeCondition adds time constraints to aggregate queries.
|
||||
func (s *SelectStatement) RewriteTimeCondition(now time.Time) error {
|
||||
interval, err := s.GroupByInterval()
|
||||
if err != nil {
|
||||
return err
|
||||
} else if interval > 0 && s.Condition != nil {
|
||||
valuer := &NowValuer{Location: s.Location}
|
||||
_, timeRange, err := ConditionExpr(s.Condition, valuer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if timeRange.Max.IsZero() {
|
||||
s.Condition = &BinaryExpr{
|
||||
Op: AND,
|
||||
LHS: s.Condition,
|
||||
RHS: &BinaryExpr{
|
||||
Op: LTE,
|
||||
LHS: &VarRef{Val: "time"},
|
||||
RHS: &TimeLiteral{Val: now},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, source := range s.Sources {
|
||||
switch source := source.(type) {
|
||||
case *SubQuery:
|
||||
if err := source.Statement.RewriteTimeCondition(now); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ColumnNames will walk all fields and functions and return the appropriate field names for the select statement
|
||||
// while maintaining order of the field names.
|
||||
func (s *SelectStatement) ColumnNames() []string {
|
||||
|
@ -1674,17 +1534,6 @@ func (s *SelectStatement) Reduce(valuer Valuer) *SelectStatement {
|
|||
return stmt
|
||||
}
|
||||
|
||||
// HasTimeFieldSpecified will walk all fields and determine if the user explicitly asked for time.
|
||||
// This is needed to determine re-write behaviors for functions like TOP and BOTTOM.
|
||||
func (s *SelectStatement) HasTimeFieldSpecified() bool {
|
||||
for _, f := range s.Fields {
|
||||
if f.Name() == "time" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// String returns a string representation of the select statement.
|
||||
func (s *SelectStatement) String() string {
|
||||
var buf bytes.Buffer
|
||||
|
@ -1889,37 +1738,6 @@ func (s *SelectStatement) rewriteWithoutTimeDimensions() string {
|
|||
return n.String()
|
||||
}
|
||||
|
||||
// NamesInWhere returns the field and tag names (idents) referenced in the where clause.
|
||||
func (s *SelectStatement) NamesInWhere() []string {
|
||||
var a []string
|
||||
if s.Condition != nil {
|
||||
a = walkNames(s.Condition)
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
// NamesInSelect returns the field and tag names (idents) in the select clause.
|
||||
func (s *SelectStatement) NamesInSelect() []string {
|
||||
var a []string
|
||||
|
||||
for _, f := range s.Fields {
|
||||
a = append(a, walkNames(f.Expr)...)
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
// NamesInDimension returns the field and tag names (idents) in the group by clause.
|
||||
func (s *SelectStatement) NamesInDimension() []string {
|
||||
var a []string
|
||||
|
||||
for _, d := range s.Dimensions {
|
||||
a = append(a, walkNames(d.Expr)...)
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
func encodeMeasurement(mm *Measurement) *internal.Measurement {
|
||||
pb := &internal.Measurement{
|
||||
Database: proto.String(mm.Database),
|
||||
|
@ -2023,57 +1841,6 @@ func ExprNames(expr Expr) []VarRef {
|
|||
return a
|
||||
}
|
||||
|
||||
// FunctionCalls returns the Call objects from the query.
|
||||
func (s *SelectStatement) FunctionCalls() []*Call {
|
||||
var a []*Call
|
||||
for _, f := range s.Fields {
|
||||
a = append(a, walkFunctionCalls(f.Expr)...)
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
// FunctionCallsByPosition returns the Call objects from the query in the order they appear in the select statement.
|
||||
func (s *SelectStatement) FunctionCallsByPosition() [][]*Call {
|
||||
var a [][]*Call
|
||||
for _, f := range s.Fields {
|
||||
a = append(a, walkFunctionCalls(f.Expr))
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
// walkFunctionCalls walks the Expr and returns any function calls made.
|
||||
func walkFunctionCalls(exp Expr) []*Call {
|
||||
switch expr := exp.(type) {
|
||||
case *VarRef:
|
||||
return nil
|
||||
case *Call:
|
||||
return []*Call{expr}
|
||||
case *BinaryExpr:
|
||||
var ret []*Call
|
||||
ret = append(ret, walkFunctionCalls(expr.LHS)...)
|
||||
ret = append(ret, walkFunctionCalls(expr.RHS)...)
|
||||
return ret
|
||||
case *ParenExpr:
|
||||
return walkFunctionCalls(expr.Expr)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MatchSource returns the source name that matches a field name.
|
||||
// It returns a blank string if no sources match.
|
||||
func MatchSource(sources Sources, name string) string {
|
||||
for _, src := range sources {
|
||||
switch src := src.(type) {
|
||||
case *Measurement:
|
||||
if strings.HasPrefix(name, src.Name) {
|
||||
return src.Name
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Target represents a target (destination) policy, measurement, and DB.
|
||||
type Target struct {
|
||||
// Measurement to write into.
|
||||
|
@ -4954,34 +4721,6 @@ func IsSelector(expr Expr) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// selectInfo represents an object that stores info about select fields.
|
||||
type selectInfo struct {
|
||||
calls map[*Call]struct{}
|
||||
refs map[*VarRef]struct{}
|
||||
}
|
||||
|
||||
// newSelectInfo creates a object with call and var ref info from stmt.
|
||||
func newSelectInfo(stmt *SelectStatement) *selectInfo {
|
||||
info := &selectInfo{
|
||||
calls: make(map[*Call]struct{}),
|
||||
refs: make(map[*VarRef]struct{}),
|
||||
}
|
||||
Walk(info, stmt.Fields)
|
||||
return info
|
||||
}
|
||||
|
||||
func (v *selectInfo) Visit(n Node) Visitor {
|
||||
switch n := n.(type) {
|
||||
case *Call:
|
||||
v.calls[n] = struct{}{}
|
||||
return nil
|
||||
case *VarRef:
|
||||
v.refs[n] = struct{}{}
|
||||
return nil
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// stringSetSlice returns a sorted slice of keys from a string set.
|
||||
func stringSetSlice(m map[string]struct{}) []string {
|
||||
if m == nil {
|
||||
|
|
|
@ -229,24 +229,6 @@ func TestSelectStatement_SetTimeRange(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// Ensure the idents from the select clause can come out
|
||||
func TestSelect_NamesInSelect(t *testing.T) {
|
||||
s := MustParseSelectStatement("select count(asdf), count(bar) from cpu")
|
||||
a := s.NamesInSelect()
|
||||
if !reflect.DeepEqual(a, []string{"asdf", "bar"}) {
|
||||
t.Fatal("expected names asdf and bar")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the idents from the where clause can come out
|
||||
func TestSelect_NamesInWhere(t *testing.T) {
|
||||
s := MustParseSelectStatement("select * from cpu where time > 23s AND (asdf = 'jkl' OR (foo = 'bar' AND baz = 'bar'))")
|
||||
a := s.NamesInWhere()
|
||||
if !reflect.DeepEqual(a, []string{"time", "asdf", "foo", "baz"}) {
|
||||
t.Fatalf("exp: time,asdf,foo,baz\ngot: %s\n", strings.Join(a, ","))
|
||||
}
|
||||
}
|
||||
|
||||
func TestSelectStatement_HasWildcard(t *testing.T) {
|
||||
var tests = []struct {
|
||||
stmt string
|
||||
|
@ -708,133 +690,6 @@ func TestSelectStatement_IsRawQuerySet(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestSelectStatement_HasDerivative(t *testing.T) {
|
||||
var tests = []struct {
|
||||
stmt string
|
||||
derivative bool
|
||||
}{
|
||||
// No derivatives
|
||||
{
|
||||
stmt: `SELECT value FROM cpu`,
|
||||
derivative: false,
|
||||
},
|
||||
|
||||
// Query derivative
|
||||
{
|
||||
stmt: `SELECT derivative(value) FROM cpu`,
|
||||
derivative: true,
|
||||
},
|
||||
|
||||
// No GROUP BY time only
|
||||
{
|
||||
stmt: `SELECT mean(value) FROM cpu where time < now() GROUP BY time(5ms)`,
|
||||
derivative: false,
|
||||
},
|
||||
|
||||
// No GROUP BY derivatives, time only
|
||||
{
|
||||
stmt: `SELECT derivative(mean(value)) FROM cpu where time < now() GROUP BY time(5ms)`,
|
||||
derivative: true,
|
||||
},
|
||||
|
||||
{
|
||||
stmt: `SELECT value FROM cpu`,
|
||||
derivative: false,
|
||||
},
|
||||
|
||||
// Query derivative
|
||||
{
|
||||
stmt: `SELECT non_negative_derivative(value) FROM cpu`,
|
||||
derivative: true,
|
||||
},
|
||||
|
||||
// No GROUP BY derivatives, time only
|
||||
{
|
||||
stmt: `SELECT non_negative_derivative(mean(value)) FROM cpu where time < now() GROUP BY time(5ms)`,
|
||||
derivative: true,
|
||||
},
|
||||
|
||||
// Invalid derivative function name
|
||||
{
|
||||
stmt: `SELECT typoDerivative(value) FROM cpu where time < now()`,
|
||||
derivative: false,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
// Parse statement.
|
||||
t.Logf("index: %d, statement: %s", i, tt.stmt)
|
||||
stmt, err := influxql.NewParser(strings.NewReader(tt.stmt)).ParseStatement()
|
||||
if err != nil {
|
||||
t.Fatalf("invalid statement: %q: %s", tt.stmt, err)
|
||||
}
|
||||
|
||||
// Test derivative detection.
|
||||
if d := stmt.(*influxql.SelectStatement).HasDerivative(); tt.derivative != d {
|
||||
t.Errorf("%d. %q: unexpected derivative detection:\n\nexp=%v\n\ngot=%v\n\n", i, tt.stmt, tt.derivative, d)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSelectStatement_IsSimpleDerivative(t *testing.T) {
|
||||
var tests = []struct {
|
||||
stmt string
|
||||
derivative bool
|
||||
}{
|
||||
// No derivatives
|
||||
{
|
||||
stmt: `SELECT value FROM cpu`,
|
||||
derivative: false,
|
||||
},
|
||||
|
||||
// Query derivative
|
||||
{
|
||||
stmt: `SELECT derivative(value) FROM cpu`,
|
||||
derivative: true,
|
||||
},
|
||||
|
||||
// Query derivative
|
||||
{
|
||||
stmt: `SELECT non_negative_derivative(value) FROM cpu`,
|
||||
derivative: true,
|
||||
},
|
||||
|
||||
// No GROUP BY time only
|
||||
{
|
||||
stmt: `SELECT mean(value) FROM cpu where time < now() GROUP BY time(5ms)`,
|
||||
derivative: false,
|
||||
},
|
||||
|
||||
// No GROUP BY derivatives, time only
|
||||
{
|
||||
stmt: `SELECT non_negative_derivative(mean(value)) FROM cpu where time < now() GROUP BY time(5ms)`,
|
||||
derivative: false,
|
||||
},
|
||||
|
||||
// Invalid derivative function name
|
||||
{
|
||||
stmt: `SELECT typoDerivative(value) FROM cpu where time < now()`,
|
||||
derivative: false,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
// Parse statement.
|
||||
t.Logf("index: %d, statement: %s", i, tt.stmt)
|
||||
stmt, err := influxql.NewParser(strings.NewReader(tt.stmt)).ParseStatement()
|
||||
if err != nil {
|
||||
t.Fatalf("invalid statement: %q: %s", tt.stmt, err)
|
||||
}
|
||||
|
||||
// Test derivative detection.
|
||||
if d := stmt.(*influxql.SelectStatement).IsSimpleDerivative(); tt.derivative != d {
|
||||
t.Errorf("%d. %q: unexpected derivative detection:\n\nexp=%v\n\ngot=%v\n\n", i, tt.stmt, tt.derivative, d)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure binary expression names can be evaluated.
|
||||
func TestBinaryExprName(t *testing.T) {
|
||||
for i, tt := range []struct {
|
||||
|
@ -1623,49 +1478,6 @@ func TestShow_Privileges(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestSources_Names(t *testing.T) {
|
||||
sources := influxql.Sources([]influxql.Source{
|
||||
&influxql.Measurement{
|
||||
Name: "cpu",
|
||||
},
|
||||
&influxql.Measurement{
|
||||
Name: "mem",
|
||||
},
|
||||
})
|
||||
|
||||
names := sources.Names()
|
||||
if names[0] != "cpu" {
|
||||
t.Errorf("expected cpu, got %s", names[0])
|
||||
}
|
||||
if names[1] != "mem" {
|
||||
t.Errorf("expected mem, got %s", names[1])
|
||||
}
|
||||
}
|
||||
|
||||
func TestSources_HasSystemSource(t *testing.T) {
|
||||
sources := influxql.Sources([]influxql.Source{
|
||||
&influxql.Measurement{
|
||||
Name: "_measurements",
|
||||
},
|
||||
})
|
||||
|
||||
ok := sources.HasSystemSource()
|
||||
if !ok {
|
||||
t.Errorf("expected to find a system source, found none")
|
||||
}
|
||||
|
||||
sources = influxql.Sources([]influxql.Source{
|
||||
&influxql.Measurement{
|
||||
Name: "cpu",
|
||||
},
|
||||
})
|
||||
|
||||
ok = sources.HasSystemSource()
|
||||
if ok {
|
||||
t.Errorf("expected to find no system source, found one")
|
||||
}
|
||||
}
|
||||
|
||||
// This test checks to ensure that we have given thought to the database
|
||||
// context required for security checks. If a new statement is added, this
|
||||
// test will fail until it is categorized into the correct bucket below.
|
||||
|
|
Loading…
Reference in New Issue