influxdb/influxql/ast.go

2781 lines
74 KiB
Go
Raw Normal View History

2014-11-15 19:04:30 +00:00
package influxql
import (
"bytes"
2015-01-23 09:44:56 +00:00
"errors"
"fmt"
"regexp"
"sort"
"strconv"
"strings"
2014-11-15 19:04:30 +00:00
"time"
)
// DataType represents the primitive data types available in InfluxQL.
type DataType string
const (
2015-02-01 18:47:48 +00:00
// Unknown primitive data type.
Unknown = DataType("")
2015-04-13 04:36:00 +00:00
// Float means the data type is a float
Float = DataType("float")
// Integer means the data type is a integer
Integer = DataType("integer")
2015-02-01 18:47:48 +00:00
// Boolean means the data type is a boolean.
Boolean = DataType("boolean")
// String means the data type is a string of text.
String = DataType("string")
// Time means the data type is a time.
Time = DataType("time")
// Duration means the data type is a duration of time.
2014-11-15 19:04:30 +00:00
Duration = DataType("duration")
)
2014-12-09 15:45:29 +00:00
// InspectDataType returns the data type of a given value.
func InspectDataType(v interface{}) DataType {
switch v.(type) {
case float64:
2015-04-13 04:36:00 +00:00
return Float
case int64, int32, int:
return Integer
2014-12-09 15:45:29 +00:00
case bool:
return Boolean
case string:
return String
case time.Time:
return Time
case time.Duration:
return Duration
default:
return Unknown
}
}
2014-11-15 19:04:30 +00:00
// Node represents a node in the InfluxDB abstract syntax tree.
type Node interface {
node()
String() string
2014-11-15 19:04:30 +00:00
}
2015-02-01 18:47:48 +00:00
func (*Query) node() {}
func (Statements) node() {}
func (*AlterRetentionPolicyStatement) node() {}
func (*CreateContinuousQueryStatement) node() {}
func (*CreateDatabaseStatement) node() {}
func (*CreateRetentionPolicyStatement) node() {}
func (*CreateUserStatement) node() {}
func (*Distinct) node() {}
2015-02-01 18:47:48 +00:00
func (*DeleteStatement) node() {}
func (*DropContinuousQueryStatement) node() {}
func (*DropDatabaseStatement) node() {}
2015-02-23 20:51:52 +00:00
func (*DropMeasurementStatement) node() {}
2015-02-01 18:47:48 +00:00
func (*DropRetentionPolicyStatement) node() {}
func (*DropSeriesStatement) node() {}
func (*DropUserStatement) node() {}
func (*GrantStatement) node() {}
func (*ShowContinuousQueriesStatement) node() {}
2015-03-10 19:46:05 +00:00
func (*ShowServersStatement) node() {}
2015-02-01 18:47:48 +00:00
func (*ShowDatabasesStatement) node() {}
func (*ShowFieldKeysStatement) node() {}
func (*ShowRetentionPoliciesStatement) node() {}
func (*ShowMeasurementsStatement) node() {}
func (*ShowSeriesStatement) node() {}
2015-03-12 23:07:41 +00:00
func (*ShowStatsStatement) node() {}
2015-03-24 03:13:54 +00:00
func (*ShowDiagnosticsStatement) node() {}
2015-02-01 18:47:48 +00:00
func (*ShowTagKeysStatement) node() {}
func (*ShowTagValuesStatement) node() {}
func (*ShowUsersStatement) node() {}
func (*RevokeStatement) node() {}
func (*SelectStatement) node() {}
func (*SetPasswordUserStatement) node() {}
2015-02-01 18:47:48 +00:00
func (*BinaryExpr) node() {}
func (*BooleanLiteral) node() {}
func (*Call) node() {}
func (*Dimension) node() {}
func (Dimensions) node() {}
func (*DurationLiteral) node() {}
func (*Field) node() {}
func (Fields) node() {}
func (*Measurement) node() {}
func (Measurements) node() {}
func (*nilLiteral) node() {}
func (*NumberLiteral) node() {}
func (*ParenExpr) node() {}
func (*RegexLiteral) node() {}
2015-02-01 18:47:48 +00:00
func (*SortField) node() {}
func (SortFields) node() {}
2015-03-06 13:52:25 +00:00
func (Sources) node() {}
2015-02-01 18:47:48 +00:00
func (*StringLiteral) node() {}
func (*Target) node() {}
func (*TimeLiteral) node() {}
func (*VarRef) node() {}
func (*Wildcard) node() {}
2014-11-15 19:04:30 +00:00
// Query represents a collection of ordered statements.
2014-11-22 04:12:48 +00:00
type Query struct {
Statements Statements
2014-11-15 19:04:30 +00:00
}
// String returns a string representation of the query.
func (q *Query) String() string { return q.Statements.String() }
2014-11-22 04:12:48 +00:00
// Statements represents a list of statements.
type Statements []Statement
// String returns a string representation of the statements.
func (a Statements) String() string {
var str []string
for _, stmt := range a {
str = append(str, stmt.String())
}
return strings.Join(str, ";\n")
}
2014-11-22 04:12:48 +00:00
// Statement represents a single command in InfluxQL.
type Statement interface {
Node
stmt()
2015-01-19 20:12:48 +00:00
RequiredPrivileges() ExecutionPrivileges
2014-11-22 04:12:48 +00:00
}
// HasDefaultDatabase provides an interface to get the default database from a Statement.
type HasDefaultDatabase interface {
Node
stmt()
DefaultDatabase() string
}
2015-01-19 20:12:48 +00:00
// ExecutionPrivilege is a privilege required for a user to execute
// a statement on a database or resource.
type ExecutionPrivilege struct {
// Name of the database or resource.
// If "", then the resource is the cluster.
Name string
// Privilege required.
Privilege Privilege
}
// ExecutionPrivileges is a list of privileges required to execute a statement.
type ExecutionPrivileges []ExecutionPrivilege
2015-02-01 18:47:48 +00:00
func (*AlterRetentionPolicyStatement) stmt() {}
func (*CreateContinuousQueryStatement) stmt() {}
func (*CreateDatabaseStatement) stmt() {}
func (*CreateRetentionPolicyStatement) stmt() {}
func (*CreateUserStatement) stmt() {}
func (*DeleteStatement) stmt() {}
func (*DropContinuousQueryStatement) stmt() {}
func (*DropDatabaseStatement) stmt() {}
2015-02-23 20:51:52 +00:00
func (*DropMeasurementStatement) stmt() {}
2015-02-01 18:47:48 +00:00
func (*DropRetentionPolicyStatement) stmt() {}
func (*DropSeriesStatement) stmt() {}
func (*DropUserStatement) stmt() {}
func (*GrantStatement) stmt() {}
func (*ShowContinuousQueriesStatement) stmt() {}
2015-03-10 19:46:05 +00:00
func (*ShowServersStatement) stmt() {}
2015-02-01 18:47:48 +00:00
func (*ShowDatabasesStatement) stmt() {}
func (*ShowFieldKeysStatement) stmt() {}
func (*ShowMeasurementsStatement) stmt() {}
func (*ShowRetentionPoliciesStatement) stmt() {}
func (*ShowSeriesStatement) stmt() {}
2015-03-12 23:07:41 +00:00
func (*ShowStatsStatement) stmt() {}
2015-03-24 03:13:54 +00:00
func (*ShowDiagnosticsStatement) stmt() {}
2015-02-01 18:47:48 +00:00
func (*ShowTagKeysStatement) stmt() {}
func (*ShowTagValuesStatement) stmt() {}
func (*ShowUsersStatement) stmt() {}
func (*RevokeStatement) stmt() {}
func (*SelectStatement) stmt() {}
func (*SetPasswordUserStatement) stmt() {}
2014-11-15 19:04:30 +00:00
// Expr represents an expression that can be evaluated to a value.
type Expr interface {
Node
expr()
}
2015-02-01 18:47:48 +00:00
func (*BinaryExpr) expr() {}
func (*BooleanLiteral) expr() {}
func (*Call) expr() {}
func (*Distinct) expr() {}
2015-02-01 18:47:48 +00:00
func (*DurationLiteral) expr() {}
func (*nilLiteral) expr() {}
func (*NumberLiteral) expr() {}
func (*ParenExpr) expr() {}
func (*RegexLiteral) expr() {}
2015-02-01 18:47:48 +00:00
func (*StringLiteral) expr() {}
func (*TimeLiteral) expr() {}
func (*VarRef) expr() {}
func (*Wildcard) expr() {}
2014-11-15 19:04:30 +00:00
2014-11-22 04:12:48 +00:00
// Source represents a source of data for a statement.
type Source interface {
2014-11-15 19:04:30 +00:00
Node
2014-11-22 04:12:48 +00:00
source()
2014-11-15 19:04:30 +00:00
}
func (*Measurement) source() {}
2015-03-06 13:52:25 +00:00
// Sources represents a list of sources.
type Sources []Source
// String returns a string representation of a Sources array.
func (a Sources) String() string {
var buf bytes.Buffer
ubound := len(a) - 1
for i, src := range a {
_, _ = buf.WriteString(src.String())
if i < ubound {
_, _ = buf.WriteString(", ")
}
}
return buf.String()
}
2014-11-15 19:04:30 +00:00
2015-01-21 13:28:24 +00:00
// SortField represents a field to sort results by.
type SortField struct {
// Name of the field
Name string
// Sort order.
Ascending bool
}
// String returns a string representation of a sort field
func (field *SortField) String() string {
var buf bytes.Buffer
_, _ = buf.WriteString(field.Name)
_, _ = buf.WriteString(" ")
_, _ = buf.WriteString(strconv.FormatBool(field.Ascending))
return buf.String()
}
// SortFields represents an ordered list of ORDER BY fields
type SortFields []*SortField
// String returns a string representation of sort fields
func (a SortFields) String() string {
fields := make([]string, 0, len(a))
for _, field := range a {
fields = append(fields, field.String())
}
return strings.Join(fields, ", ")
}
2014-12-31 13:47:21 +00:00
// CreateDatabaseStatement represents a command for creating a new database.
type CreateDatabaseStatement struct {
// Name of the database to be created.
Name string
}
// String returns a string representation of the create database statement.
func (s *CreateDatabaseStatement) String() string {
var buf bytes.Buffer
_, _ = buf.WriteString("CREATE DATABASE ")
_, _ = buf.WriteString(s.Name)
return buf.String()
}
2015-02-01 18:47:48 +00:00
// RequiredPrivileges returns the privilege required to execute a CreateDatabaseStatement.
2015-01-19 20:12:48 +00:00
func (s *CreateDatabaseStatement) RequiredPrivileges() ExecutionPrivileges {
2015-01-21 18:06:59 +00:00
return ExecutionPrivileges{{Name: "", Privilege: AllPrivileges}}
2015-01-19 20:12:48 +00:00
}
2015-01-05 03:32:49 +00:00
// DropDatabaseStatement represents a command to drop a database.
type DropDatabaseStatement struct {
// Name of the database to be dropped.
Name string
}
// String returns a string representation of the drop database statement.
func (s *DropDatabaseStatement) String() string {
var buf bytes.Buffer
_, _ = buf.WriteString("DROP DATABASE ")
_, _ = buf.WriteString(s.Name)
return buf.String()
}
2015-02-01 18:47:48 +00:00
// RequiredPrivileges returns the privilege required to execute a DropDatabaseStatement.
2015-01-19 20:12:48 +00:00
func (s *DropDatabaseStatement) RequiredPrivileges() ExecutionPrivileges {
2015-01-21 18:06:59 +00:00
return ExecutionPrivileges{{Name: "", Privilege: AllPrivileges}}
2015-01-19 20:12:48 +00:00
}
// DropRetentionPolicyStatement represents a command to drop a retention policy from a database.
type DropRetentionPolicyStatement struct {
// Name of the policy to drop.
Name string
// Name of the database to drop the policy from.
Database string
}
// String returns a string representation of the drop retention policy statement.
func (s *DropRetentionPolicyStatement) String() string {
var buf bytes.Buffer
_, _ = buf.WriteString("DROP RETENTION POLICY ")
_, _ = buf.WriteString(s.Name)
_, _ = buf.WriteString(" ON ")
_, _ = buf.WriteString(s.Database)
return buf.String()
}
2015-02-01 18:47:48 +00:00
// RequiredPrivileges returns the privilege required to execute a DropRetentionPolicyStatement.
2015-01-19 20:12:48 +00:00
func (s *DropRetentionPolicyStatement) RequiredPrivileges() ExecutionPrivileges {
2015-01-21 18:06:59 +00:00
return ExecutionPrivileges{{Name: s.Database, Privilege: WritePrivilege}}
2015-01-19 20:12:48 +00:00
}
2014-12-31 16:22:07 +00:00
// CreateUserStatement represents a command for creating a new user.
type CreateUserStatement struct {
// Name of the user to be created.
Name string
// User's password
Password string
// User's privilege level.
Privilege *Privilege
2014-12-31 16:22:07 +00:00
}
// String returns a string representation of the create user statement.
func (s *CreateUserStatement) String() string {
var buf bytes.Buffer
_, _ = buf.WriteString("CREATE USER ")
_, _ = buf.WriteString(s.Name)
_, _ = buf.WriteString(" WITH PASSWORD ")
_, _ = buf.WriteString(s.Password)
if s.Privilege != nil {
_, _ = buf.WriteString(" WITH ")
_, _ = buf.WriteString(s.Privilege.String())
}
2014-12-31 16:22:07 +00:00
return buf.String()
}
2015-02-01 18:47:48 +00:00
// RequiredPrivileges returns the privilege(s) required to execute a CreateUserStatement.
2015-01-19 20:12:48 +00:00
func (s *CreateUserStatement) RequiredPrivileges() ExecutionPrivileges {
2015-01-21 18:06:59 +00:00
return ExecutionPrivileges{{Name: "", Privilege: AllPrivileges}}
2015-01-19 20:12:48 +00:00
}
2015-01-05 03:56:25 +00:00
// DropUserStatement represents a command for dropping a user.
type DropUserStatement struct {
// Name of the user to drop.
Name string
}
// String returns a string representation of the drop user statement.
func (s *DropUserStatement) String() string {
var buf bytes.Buffer
_, _ = buf.WriteString("DROP USER ")
_, _ = buf.WriteString(s.Name)
return buf.String()
}
2015-02-01 18:47:48 +00:00
// RequiredPrivileges returns the privilege(s) required to execute a DropUserStatement.
2015-01-19 20:12:48 +00:00
func (s *DropUserStatement) RequiredPrivileges() ExecutionPrivileges {
2015-01-21 18:06:59 +00:00
return ExecutionPrivileges{{Name: "", Privilege: AllPrivileges}}
2015-01-19 20:12:48 +00:00
}
2015-01-03 03:56:26 +00:00
// Privilege is a type of action a user can be granted the right to use.
type Privilege int
const (
2015-02-01 18:47:48 +00:00
// NoPrivileges means no privileges required / granted / revoked.
2015-01-19 20:12:48 +00:00
NoPrivileges Privilege = iota
2015-02-01 18:47:48 +00:00
// ReadPrivilege means read privilege required / granted / revoked.
2015-01-19 20:12:48 +00:00
ReadPrivilege
2015-02-01 18:47:48 +00:00
// WritePrivilege means write privilege required / granted / revoked.
2015-01-03 03:56:26 +00:00
WritePrivilege
2015-02-01 18:47:48 +00:00
// AllPrivileges means all privileges required / granted / revoked.
2015-01-03 03:56:26 +00:00
AllPrivileges
)
// NewPrivilege returns an initialized *Privilege.
func NewPrivilege(p Privilege) *Privilege { return &p }
2015-01-03 03:56:26 +00:00
// String returns a string representation of a Privilege.
func (p Privilege) String() string {
switch p {
2015-01-19 20:12:48 +00:00
case NoPrivileges:
return "NO PRIVILEGES"
2015-01-03 03:56:26 +00:00
case ReadPrivilege:
return "READ"
case WritePrivilege:
return "WRITE"
case AllPrivileges:
return "ALL PRIVILEGES"
}
return ""
}
// GrantStatement represents a command for granting a privilege.
type GrantStatement struct {
// The privilege to be granted.
Privilege Privilege
// Thing to grant privilege on (e.g., a DB).
On string
// Who to grant the privilege to.
User string
}
// String returns a string representation of the grant statement.
func (s *GrantStatement) String() string {
var buf bytes.Buffer
_, _ = buf.WriteString("GRANT ")
_, _ = buf.WriteString(s.Privilege.String())
2015-01-03 07:06:18 +00:00
if s.On != "" {
_, _ = buf.WriteString(" ON ")
_, _ = buf.WriteString(s.On)
}
2015-01-03 03:56:26 +00:00
_, _ = buf.WriteString(" TO ")
_, _ = buf.WriteString(s.User)
return buf.String()
}
2015-02-01 18:47:48 +00:00
// RequiredPrivileges returns the privilege required to execute a GrantStatement.
2015-01-19 20:12:48 +00:00
func (s *GrantStatement) RequiredPrivileges() ExecutionPrivileges {
2015-01-21 18:06:59 +00:00
return ExecutionPrivileges{{Name: "", Privilege: AllPrivileges}}
2015-01-19 20:12:48 +00:00
}
// SetPasswordUserStatement represents a command for chaning user password.
type SetPasswordUserStatement struct {
// Plain Password
Password string
// Who to grant the privilege to.
Name string
}
// String returns a string representation of the set password statement.
func (s *SetPasswordUserStatement) String() string {
var buf bytes.Buffer
_, _ = buf.WriteString("SET PASSWORD FOR ")
_, _ = buf.WriteString(s.Name)
_, _ = buf.WriteString(" = ")
_, _ = buf.WriteString(s.Password)
return buf.String()
}
// RequiredPrivileges returns the privilege required to execute a GrantStatement.
func (s *SetPasswordUserStatement) RequiredPrivileges() ExecutionPrivileges {
return ExecutionPrivileges{{Name: "", Privilege: AllPrivileges}}
}
2015-01-03 07:06:18 +00:00
// RevokeStatement represents a command to revoke a privilege from a user.
type RevokeStatement struct {
// Privilege to be revoked.
Privilege Privilege
// Thing to revoke privilege to (e.g., a DB)
On string
// Who to revoke privilege from.
User string
}
// String returns a string representation of the revoke statement.
func (s *RevokeStatement) String() string {
var buf bytes.Buffer
_, _ = buf.WriteString("REVOKE ")
_, _ = buf.WriteString(s.Privilege.String())
if s.On != "" {
_, _ = buf.WriteString(" ON ")
_, _ = buf.WriteString(s.On)
}
_, _ = buf.WriteString(" FROM ")
_, _ = buf.WriteString(s.User)
return buf.String()
}
2015-02-01 18:47:48 +00:00
// RequiredPrivileges returns the privilege required to execute a RevokeStatement.
2015-01-19 20:12:48 +00:00
func (s *RevokeStatement) RequiredPrivileges() ExecutionPrivileges {
2015-01-21 18:06:59 +00:00
return ExecutionPrivileges{{Name: "", Privilege: AllPrivileges}}
2015-01-19 20:12:48 +00:00
}
// CreateRetentionPolicyStatement represents a command to create a retention policy.
type CreateRetentionPolicyStatement struct {
// Name of policy to create.
Name string
// Name of database this policy belongs to.
Database string
// Duration data written to this policy will be retained.
Duration time.Duration
// Replication factor for data written to this policy.
Replication int
// Should this policy be set as default for the database?
Default bool
}
// String returns a string representation of the create retention policy.
func (s *CreateRetentionPolicyStatement) String() string {
var buf bytes.Buffer
_, _ = buf.WriteString("CREATE RETENTION POLICY ")
_, _ = buf.WriteString(s.Name)
_, _ = buf.WriteString(" ON ")
_, _ = buf.WriteString(s.Database)
_, _ = buf.WriteString(" DURATION ")
_, _ = buf.WriteString(FormatDuration(s.Duration))
_, _ = buf.WriteString(" REPLICATION ")
_, _ = buf.WriteString(strconv.Itoa(s.Replication))
if s.Default {
_, _ = buf.WriteString(" DEFAULT")
}
return buf.String()
}
2015-02-01 18:47:48 +00:00
// RequiredPrivileges returns the privilege required to execute a CreateRetentionPolicyStatement.
2015-01-19 20:12:48 +00:00
func (s *CreateRetentionPolicyStatement) RequiredPrivileges() ExecutionPrivileges {
2015-01-21 18:06:59 +00:00
return ExecutionPrivileges{{Name: "", Privilege: AllPrivileges}}
2015-01-19 20:12:48 +00:00
}
// AlterRetentionPolicyStatement represents a command to alter an existing retention policy.
type AlterRetentionPolicyStatement struct {
// Name of policy to alter.
Name string
// Name of the database this policy belongs to.
Database string
// Duration data written to this policy will be retained.
Duration *time.Duration
// Replication factor for data written to this policy.
Replication *int
// Should this policy be set as defalut for the database?
Default bool
}
// String returns a string representation of the alter retention policy statement.
func (s *AlterRetentionPolicyStatement) String() string {
var buf bytes.Buffer
_, _ = buf.WriteString("ALTER RETENTION POLICY ")
_, _ = buf.WriteString(s.Name)
_, _ = buf.WriteString(" ON ")
_, _ = buf.WriteString(s.Database)
if s.Duration != nil {
_, _ = buf.WriteString(" DURATION ")
_, _ = buf.WriteString(FormatDuration(*s.Duration))
}
if s.Replication != nil {
_, _ = buf.WriteString(" REPLICATION ")
_, _ = buf.WriteString(strconv.Itoa(*s.Replication))
}
if s.Default {
_, _ = buf.WriteString(" DEFAULT")
}
return buf.String()
}
2015-02-01 18:47:48 +00:00
// RequiredPrivileges returns the privilege required to execute an AlterRetentionPolicyStatement.
2015-01-19 20:12:48 +00:00
func (s *AlterRetentionPolicyStatement) RequiredPrivileges() ExecutionPrivileges {
2015-01-21 18:06:59 +00:00
return ExecutionPrivileges{{Name: "", Privilege: AllPrivileges}}
2015-01-19 20:12:48 +00:00
}
type FillOption int
const (
// NullFill means that empty aggregate windows will just have null values.
NullFill FillOption = iota
// NoFill means that empty aggregate windows will be purged from the result.
NoFill
2015-03-12 01:20:20 +00:00
// NumberFill means that empty aggregate windows will be filled with the given number
NumberFill
// PreviousFill means that empty aggregate windows will be filled with whatever the previous aggregate window had
PreviousFill
)
2014-11-22 04:12:48 +00:00
// SelectStatement represents a command for extracting data from the database.
type SelectStatement struct {
2014-11-15 19:04:30 +00:00
// Expressions returned from the selection.
Fields Fields
// Target (destination) for the result of the select.
Target *Target
2014-11-15 19:04:30 +00:00
// Expressions used for grouping the selection.
Dimensions Dimensions
2015-03-06 13:52:25 +00:00
// Data sources that fields are extracted from.
Sources Sources
2014-11-15 19:04:30 +00:00
// An expression evaluated on data point.
Condition Expr
// Fields to sort results by
SortFields SortFields
// Maximum number of rows to be returned. Unlimited if zero.
2014-11-15 19:04:30 +00:00
Limit int
2015-01-25 20:34:49 +00:00
// Returns rows starting at an offset from the first row.
Offset int
// Maxiumum number of series to be returned. Unlimited if zero.
SLimit int
// Returns series starting at an offset from the first one.
SOffset int
// memoize the group by interval
groupByInterval time.Duration
// if it's a query for raw data values (i.e. not an aggregate)
IsRawQuery bool
// What fill option the select statement uses, if any
Fill FillOption
// The value to fill empty aggregate buckets with, if any
FillValue interface{}
2014-11-15 19:04:30 +00:00
}
2015-05-14 20:53:17 +00:00
// HasDerivative returns true if one of the function calls in the statement is a
// derivative aggregate
func (s *SelectStatement) HasDerivative() bool {
2015-05-14 20:53:17 +00:00
for _, f := range s.FunctionCalls() {
if strings.HasSuffix(f.Name, "derivative") {
return true
}
}
return false
}
2015-05-14 20:53:17 +00:00
// IsSimpleDerivative return true if one of the function call is a derivative function with a
// variable ref as the first arg
func (s *SelectStatement) IsSimpleDerivative() bool {
2015-05-14 20:53:17 +00:00
for _, f := range s.FunctionCalls() {
if strings.HasSuffix(f.Name, "derivative") {
// it's nested if the first argument is an aggregate function
if _, ok := f.Args[0].(*VarRef); ok {
return true
}
}
}
return false
}
2015-01-26 12:19:35 +00:00
// Clone returns a deep copy of the statement.
2015-02-01 18:47:48 +00:00
func (s *SelectStatement) Clone() *SelectStatement {
2015-03-06 13:52:25 +00:00
clone := &SelectStatement{
Fields: make(Fields, 0, len(s.Fields)),
Dimensions: make(Dimensions, 0, len(s.Dimensions)),
Sources: cloneSources(s.Sources),
SortFields: make(SortFields, 0, len(s.SortFields)),
2015-02-01 18:47:48 +00:00
Condition: CloneExpr(s.Condition),
Limit: s.Limit,
Offset: s.Offset,
SLimit: s.SLimit,
SOffset: s.SOffset,
Fill: s.Fill,
FillValue: s.FillValue,
IsRawQuery: s.IsRawQuery,
2015-01-26 12:19:35 +00:00
}
2015-02-01 18:47:48 +00:00
if s.Target != nil {
clone.Target = &Target{
Measurement: &Measurement{
Database: s.Target.Measurement.Database,
RetentionPolicy: s.Target.Measurement.RetentionPolicy,
Name: s.Target.Measurement.Name,
Regex: CloneRegexLiteral(s.Target.Measurement.Regex),
},
}
2015-01-26 12:19:35 +00:00
}
2015-03-06 13:52:25 +00:00
for _, f := range s.Fields {
clone.Fields = append(clone.Fields, &Field{Expr: CloneExpr(f.Expr), Alias: f.Alias})
2015-01-26 12:19:35 +00:00
}
2015-03-06 13:52:25 +00:00
for _, d := range s.Dimensions {
clone.Dimensions = append(clone.Dimensions, &Dimension{Expr: CloneExpr(d.Expr)})
2015-01-26 12:19:35 +00:00
}
2015-03-06 13:52:25 +00:00
for _, f := range s.SortFields {
clone.SortFields = append(clone.SortFields, &SortField{Name: f.Name, Ascending: f.Ascending})
2015-01-26 12:19:35 +00:00
}
2015-03-06 13:52:25 +00:00
return clone
}
func cloneSources(sources Sources) Sources {
clone := make(Sources, 0, len(sources))
for _, s := range sources {
clone = append(clone, cloneSource(s))
}
return clone
2015-01-26 12:19:35 +00:00
}
func cloneSource(s Source) Source {
if s == nil {
return nil
}
switch s := s.(type) {
case *Measurement:
m := &Measurement{Database: s.Database, RetentionPolicy: s.RetentionPolicy, Name: s.Name}
2015-03-06 13:52:25 +00:00
if s.Regex != nil {
m.Regex = &RegexLiteral{Val: regexp.MustCompile(s.Regex.Val.String())}
2015-01-26 12:19:35 +00:00
}
2015-03-06 13:52:25 +00:00
return m
2015-01-26 12:19:35 +00:00
default:
panic("unreachable")
}
}
// RewriteWildcards returns the re-written form of the select statement. Any wildcard query
// fields are replaced with the supplied fields, and any wildcard GROUP BY fields are replaced
// with the supplied dimensions.
func (s *SelectStatement) RewriteWildcards(fields Fields, dimensions Dimensions) *SelectStatement {
other := s.Clone()
// Rewrite all wildcard query fields
rwFields := make(Fields, 0, len(s.Fields))
for _, f := range s.Fields {
switch f.Expr.(type) {
case *Wildcard:
// Sort wildcard fields for consistent output
sort.Sort(fields)
rwFields = append(rwFields, fields...)
default:
rwFields = append(rwFields, f)
}
}
other.Fields = rwFields
// Rewrite all wildcard GROUP BY fields
rwDimensions := make(Dimensions, 0, len(s.Dimensions))
for _, d := range s.Dimensions {
switch d.Expr.(type) {
case *Wildcard:
rwDimensions = append(rwDimensions, dimensions...)
default:
rwDimensions = append(rwDimensions, d)
}
}
other.Dimensions = rwDimensions
return other
}
// RewriteDistinct rewrites the expresion to be a call for map/reduce to work correctly
// This method assumes all validation has passed
func (s *SelectStatement) RewriteDistinct() *SelectStatement {
2015-05-18 22:28:13 +00:00
if !s.HasDistinct() {
return s
}
other := s.Clone()
// Rewrite any `distinct foo` as `distinct(foo)`
rwFields := make(Fields, 0, len(s.Fields))
for _, f := range s.Fields {
switch v := f.Expr.(type) {
case *Distinct:
field := &Field{Expr: &Call{Name: "distinct", Args: []Expr{&VarRef{Val: v.Val}}}}
rwFields = append(rwFields, field)
default:
rwFields = append(rwFields, f)
}
}
other.Fields = rwFields
other.IsRawQuery = false
return other
}
// String returns a string representation of the select statement.
func (s *SelectStatement) String() string {
var buf bytes.Buffer
_, _ = buf.WriteString("SELECT ")
_, _ = buf.WriteString(s.Fields.String())
if s.Target != nil {
_, _ = buf.WriteString(" ")
_, _ = buf.WriteString(s.Target.String())
}
2015-03-06 13:52:25 +00:00
if len(s.Sources) > 0 {
_, _ = buf.WriteString(" FROM ")
_, _ = buf.WriteString(s.Sources.String())
}
if s.Condition != nil {
_, _ = buf.WriteString(" WHERE ")
_, _ = buf.WriteString(s.Condition.String())
}
if len(s.Dimensions) > 0 {
_, _ = buf.WriteString(" GROUP BY ")
_, _ = buf.WriteString(s.Dimensions.String())
}
switch s.Fill {
case NoFill:
_, _ = buf.WriteString(" fill(none)")
case NumberFill:
_, _ = buf.WriteString(fmt.Sprintf(" fill(%v)", s.FillValue))
case PreviousFill:
_, _ = buf.WriteString(" fill(previous)")
}
if len(s.SortFields) > 0 {
_, _ = buf.WriteString(" ORDER BY ")
_, _ = buf.WriteString(s.SortFields.String())
}
if s.Limit > 0 {
_, _ = fmt.Fprintf(&buf, " LIMIT %d", s.Limit)
}
2015-01-25 20:34:49 +00:00
if s.Offset > 0 {
_, _ = buf.WriteString(" OFFSET ")
_, _ = buf.WriteString(strconv.Itoa(s.Offset))
}
return buf.String()
}
2015-02-01 18:47:48 +00:00
// RequiredPrivileges returns the privilege required to execute the SelectStatement.
2015-01-19 20:12:48 +00:00
func (s *SelectStatement) RequiredPrivileges() ExecutionPrivileges {
2015-01-21 18:06:59 +00:00
ep := ExecutionPrivileges{{Name: "", Privilege: ReadPrivilege}}
2015-01-19 20:12:48 +00:00
if s.Target != nil {
p := ExecutionPrivilege{Name: s.Target.Measurement.Database, Privilege: WritePrivilege}
2015-01-19 20:12:48 +00:00
ep = append(ep, p)
}
return ep
}
// OnlyTimeDimensions returns true if the statement has a where clause with only time constraints
func (s *SelectStatement) OnlyTimeDimensions() bool {
return s.walkForTime(s.Condition)
}
// walkForTime is called by the OnlyTimeDimensions method to walk the where clause to determine if
// the only things specified are based on time
func (s *SelectStatement) walkForTime(node Node) bool {
switch n := node.(type) {
case *BinaryExpr:
if n.Op == AND || n.Op == OR {
return s.walkForTime(n.LHS) && s.walkForTime(n.RHS)
}
if ref, ok := n.LHS.(*VarRef); ok && strings.ToLower(ref.Val) == "time" {
return true
}
return false
case *ParenExpr:
// walk down the tree
return s.walkForTime(n.Expr)
default:
return false
}
}
// HasWildcard returns whether or not the select statement has at least 1 wildcard
func (s *SelectStatement) HasWildcard() bool {
for _, f := range s.Fields {
_, ok := f.Expr.(*Wildcard)
if ok {
return true
}
}
for _, d := range s.Dimensions {
_, ok := d.Expr.(*Wildcard)
if ok {
return true
}
}
return false
}
2015-05-11 22:22:50 +00:00
// hasTimeDimensions returns whether or not the select statement has at least 1
// where condition with time as the condition
2015-05-11 22:22:50 +00:00
func (s *SelectStatement) hasTimeDimensions(node Node) bool {
switch n := node.(type) {
case *BinaryExpr:
if n.Op == AND || n.Op == OR {
return s.hasTimeDimensions(n.LHS) || s.hasTimeDimensions(n.RHS)
}
if ref, ok := n.LHS.(*VarRef); ok && strings.ToLower(ref.Val) == "time" {
return true
}
return false
case *ParenExpr:
// walk down the tree
return s.hasTimeDimensions(n.Expr)
default:
return false
}
}
2015-05-12 14:42:39 +00:00
// Validate checks certain edge conditions to determine if this is a valid select statment
func (s *SelectStatement) Validate(tr targetRequirement) error {
if err := s.ValidateDistinct(); err != nil {
2015-05-12 20:30:01 +00:00
return err
}
if err := s.ValidateAggregates(tr); err != nil {
2015-05-12 20:30:01 +00:00
return err
}
if err := s.validateDerivative(); err != nil {
return err
}
return nil
}
func (s *SelectStatement) ValidateAggregates(tr targetRequirement) error {
2015-05-12 14:56:38 +00:00
// fetch the group by duration
groupByDuration, _ := s.GroupByInterval()
2015-05-12 14:42:39 +00:00
// If we have a group by interval, but no aggregate function, it's an invalid statement
if s.IsRawQuery && groupByDuration > 0 {
2015-05-12 14:42:39 +00:00
return fmt.Errorf("GROUP BY requires at least one aggregate function")
}
// If we have an aggregate function with a group by time without a where clause, it's an invalid statement
if tr == targetNotRequired { // ignore create continuous query statements
if !s.IsRawQuery && groupByDuration > 0 && !s.hasTimeDimensions(s.Condition) {
2015-05-12 14:42:39 +00:00
return fmt.Errorf("aggregate functions with GROUP BY time require a WHERE time clause")
}
}
2015-05-12 20:30:01 +00:00
return nil
}
2015-05-18 22:28:13 +00:00
func (s *SelectStatement) HasDistinct() bool {
// determine if we have a call named distinct
for _, f := range s.Fields {
switch c := f.Expr.(type) {
case *Call:
if c.Name == "distinct" {
return true
}
case *Distinct:
return true
}
}
return false
}
// ValdiateDistinct ensures we have a properly constructed distinct statement
2015-05-12 20:30:01 +00:00
func (s *SelectStatement) ValidateDistinct() error {
2015-05-18 22:28:13 +00:00
if !s.HasDistinct() {
return nil
}
2015-05-12 14:42:39 +00:00
if len(s.Fields) > 1 {
return fmt.Errorf("aggregate function distinct() can not be combined with other functions or fields")
}
switch c := s.Fields[0].Expr.(type) {
case *Call:
if len(c.Args) == 0 {
return fmt.Errorf("distinct function requires at least one argument")
}
2015-05-15 21:58:00 +00:00
if len(c.Args) != 1 {
return fmt.Errorf("distinct function can only have one argument")
}
2015-05-15 21:58:00 +00:00
}
return nil
}
func (s *SelectStatement) validateDerivative() error {
if !s.HasDerivative() {
return nil
}
// If a derivative is requested, it must be the only field in the query. We don't support
// multiple fields in combination w/ derivaties yet.
if len(s.Fields) != 1 {
return fmt.Errorf("derivative cannot be used with other fields")
}
aggr := s.FunctionCalls()
if len(aggr) != 1 {
return fmt.Errorf("derivative cannot be used with other fields")
}
// Derivative requires two arguments
derivativeCall := aggr[0]
if len(derivativeCall.Args) == 0 {
return fmt.Errorf("derivative requires a field argument")
}
// First arg must be a field or aggr over a field e.g. (mean(field))
_, callOk := derivativeCall.Args[0].(*Call)
_, varOk := derivativeCall.Args[0].(*VarRef)
if !(callOk || varOk) {
return fmt.Errorf("derivative requires a field argument")
}
// If a duration arg is pased, make sure it's a duration
if len(derivativeCall.Args) == 2 {
// Second must be a duration .e.g (1h)
if _, ok := derivativeCall.Args[1].(*DurationLiteral); !ok {
return fmt.Errorf("derivative requires a duration argument")
}
}
2015-05-12 14:42:39 +00:00
return nil
}
// GroupByIterval extracts the time interval, if specified.
func (s *SelectStatement) GroupByInterval() (time.Duration, error) {
// return if we've already pulled it out
if s.groupByInterval != 0 {
return s.groupByInterval, nil
}
// Ignore if there are no dimensions.
if len(s.Dimensions) == 0 {
return 0, nil
}
for _, d := range s.Dimensions {
2015-05-01 15:29:39 +00:00
if call, ok := d.Expr.(*Call); ok && call.Name == "time" {
// Make sure there is exactly one argument.
if len(call.Args) != 1 {
return 0, errors.New("time dimension expected one argument")
}
// Ensure the argument is a duration.
lit, ok := call.Args[0].(*DurationLiteral)
if !ok {
return 0, errors.New("time dimension must have one duration argument")
}
s.groupByInterval = lit.Val
return lit.Val, nil
}
}
return 0, nil
}
// SetTimeRange sets the start and end time of the select statement to [start, end). i.e. start inclusive, end exclusive.
// This is used commonly for continuous queries so the start and end are in buckets.
func (s *SelectStatement) SetTimeRange(start, end time.Time) error {
cond := fmt.Sprintf("time >= '%s' AND time < '%s'", start.UTC().Format(time.RFC3339Nano), end.UTC().Format(time.RFC3339Nano))
if s.Condition != nil {
cond = fmt.Sprintf("%s AND %s", s.rewriteWithoutTimeDimensions(), cond)
}
expr, err := NewParser(strings.NewReader(cond)).ParseExpr()
if err != nil {
return err
}
// fold out any previously replaced time dimensios and set the condition
s.Condition = Reduce(expr, nil)
return nil
}
// rewriteWithoutTimeDimensions will remove any WHERE time... clauses from the select statement
// This is necessary when setting an explicit time range to override any that previously existed.
func (s *SelectStatement) rewriteWithoutTimeDimensions() string {
n := RewriteFunc(s.Condition, func(n Node) Node {
switch n := n.(type) {
case *BinaryExpr:
if n.LHS.String() == "time" {
return &BooleanLiteral{Val: true}
}
return n
2015-01-28 05:11:48 +00:00
case *Call:
return &BooleanLiteral{Val: true}
default:
return n
}
})
2015-01-28 05:11:48 +00:00
return n.String()
}
2014-12-10 14:44:52 +00:00
/*
BinaryExpr
SELECT mean(xxx.value) + avg(yyy.value) FROM xxx JOIN yyy WHERE xxx.host = 123
from xxx where host = 123
select avg(value) from yyy where host = 123
SELECT xxx.value FROM xxx WHERE xxx.host = 123
SELECT yyy.value FROM yyy
---
SELECT MEAN(xxx.value) + MEAN(cpu.load.value)
FROM xxx JOIN yyy
GROUP BY host
WHERE (xxx.region == "uswest" OR yyy.region == "uswest") AND xxx.otherfield == "XXX"
select * from (
select mean + mean from xxx join yyy
group by time(5m), host
) (xxx.region == "uswest" OR yyy.region == "uswest") AND xxx.otherfield == "XXX"
(seriesIDS for xxx.region = 'uswest' union seriesIDs for yyy.regnion = 'uswest') | seriesIDS xxx.otherfield = 'XXX'
WHERE xxx.region == "uswest" AND xxx.otherfield == "XXX"
WHERE yyy.region == "uswest"
*/
// Substatement returns a single-series statement for a given variable reference.
func (s *SelectStatement) Substatement(ref *VarRef) (*SelectStatement, error) {
// Copy dimensions and properties to new statement.
other := &SelectStatement{
Fields: Fields{{Expr: ref}},
Dimensions: s.Dimensions,
Limit: s.Limit,
Offset: s.Offset,
2014-12-16 14:06:28 +00:00
SortFields: s.SortFields,
}
// If there is only one series source then return it with the whole condition.
2015-03-06 13:52:25 +00:00
if len(s.Sources) == 1 {
other.Sources = s.Sources
other.Condition = s.Condition
return other, nil
}
// Find the matching source.
2015-03-06 13:52:25 +00:00
name := MatchSource(s.Sources, ref.Val)
if name == "" {
return nil, fmt.Errorf("field source not found: %s", ref.Val)
}
2015-03-06 13:52:25 +00:00
other.Sources = append(other.Sources, &Measurement{Name: name})
// Filter out conditions.
if s.Condition != nil {
other.Condition = filterExprBySource(name, s.Condition)
}
return other, nil
}
2015-03-06 19:23:58 +00:00
// 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)
2015-03-06 19:23:58 +00:00
}
return a
}
2015-03-06 19:23:58 +00:00
// 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)...)
}
2015-03-06 19:23:58 +00:00
return a
}
// walkNames will walk the Expr and return the database fields
func walkNames(exp Expr) []string {
switch expr := exp.(type) {
case *VarRef:
2015-03-06 19:23:58 +00:00
return []string{expr.Val}
case *Call:
if len(expr.Args) == 0 {
return nil
}
lit, ok := expr.Args[0].(*VarRef)
if !ok {
return nil
}
2015-03-06 19:23:58 +00:00
return []string{lit.Val}
case *BinaryExpr:
2015-03-06 19:23:58 +00:00
var ret []string
ret = append(ret, walkNames(expr.LHS)...)
ret = append(ret, walkNames(expr.RHS)...)
return ret
case *ParenExpr:
return walkNames(expr.Expr)
}
return nil
}
// 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
}
// walkFunctionCalls walks the Field of a query for 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
}
2014-12-31 22:34:46 +00:00
// filters an expression to exclude expressions unrelated to a source.
func filterExprBySource(name string, expr Expr) Expr {
switch expr := expr.(type) {
case *VarRef:
if !strings.HasPrefix(expr.Val, name) {
return nil
}
case *BinaryExpr:
lhs := filterExprBySource(name, expr.LHS)
rhs := filterExprBySource(name, expr.RHS)
// If an expr is logical then return either LHS/RHS or both.
// If an expr is arithmetic or comparative then require both sides.
if expr.Op == AND || expr.Op == OR {
if lhs == nil && rhs == nil {
return nil
} else if lhs != nil && rhs == nil {
return lhs
} else if lhs == nil && rhs != nil {
return rhs
}
} else {
if lhs == nil || rhs == nil {
return nil
}
}
return &BinaryExpr{Op: expr.Op, LHS: lhs, RHS: rhs}
case *ParenExpr:
exp := filterExprBySource(name, expr.Expr)
if exp == nil {
return nil
}
return &ParenExpr{Expr: exp}
}
return expr
}
// MatchSource returns the source name that matches a field name.
// Returns a blank string if no sources match.
2015-03-06 13:52:25 +00:00
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, measurment, and DB.
type Target struct {
// Measurement to write into.
Measurement *Measurement
}
// String returns a string representation of the Target.
func (t *Target) String() string {
if t == nil {
return ""
}
var buf bytes.Buffer
_, _ = buf.WriteString("INTO ")
_, _ = buf.WriteString(t.Measurement.String())
return buf.String()
}
2014-11-22 04:12:48 +00:00
// DeleteStatement represents a command for removing data from the database.
type DeleteStatement struct {
2014-11-15 19:04:30 +00:00
// Data source that values are removed from.
2014-11-22 04:12:48 +00:00
Source Source
2014-11-15 19:04:30 +00:00
// An expression evaluated on data point.
Condition Expr
}
// String returns a string representation of the delete statement.
func (s *DeleteStatement) String() string {
var buf bytes.Buffer
_, _ = buf.WriteString("DELETE ")
_, _ = buf.WriteString(s.Source.String())
if s.Condition != nil {
_, _ = buf.WriteString(" WHERE ")
_, _ = buf.WriteString(s.Condition.String())
}
return s.String()
}
2015-02-01 18:47:48 +00:00
// RequiredPrivileges returns the privilege required to execute a DeleteStatement.
2015-01-19 20:12:48 +00:00
func (s *DeleteStatement) RequiredPrivileges() ExecutionPrivileges {
2015-01-21 18:06:59 +00:00
return ExecutionPrivileges{{Name: "", Privilege: WritePrivilege}}
2015-01-19 20:12:48 +00:00
}
2015-01-26 03:40:50 +00:00
// ShowSeriesStatement represents a command for listing series in the database.
type ShowSeriesStatement struct {
2015-01-28 04:36:19 +00:00
// Measurement(s) the series are listed for.
Source Source
// An expression evaluated on a series name or tag.
Condition Expr
// Fields to sort results by
SortFields SortFields
// Maximum number of rows to be returned.
// Unlimited if zero.
Limit int
2015-01-25 20:34:49 +00:00
// Returns rows starting at an offset from the first row.
Offset int
}
// String returns a string representation of the list series statement.
2015-01-26 03:40:50 +00:00
func (s *ShowSeriesStatement) String() string {
var buf bytes.Buffer
2015-01-26 03:40:50 +00:00
_, _ = buf.WriteString("SHOW SERIES")
if s.Condition != nil {
_, _ = buf.WriteString(" WHERE ")
_, _ = buf.WriteString(s.Condition.String())
}
if len(s.SortFields) > 0 {
_, _ = buf.WriteString(" ORDER BY ")
_, _ = buf.WriteString(s.SortFields.String())
}
if s.Limit > 0 {
_, _ = buf.WriteString(" LIMIT ")
_, _ = buf.WriteString(strconv.Itoa(s.Limit))
}
2015-01-25 20:34:49 +00:00
if s.Offset > 0 {
_, _ = buf.WriteString(" OFFSET ")
_, _ = buf.WriteString(strconv.Itoa(s.Offset))
}
return buf.String()
}
2015-02-01 18:47:48 +00:00
// RequiredPrivileges returns the privilege required to execute a ShowSeriesStatement.
2015-01-26 03:40:50 +00:00
func (s *ShowSeriesStatement) RequiredPrivileges() ExecutionPrivileges {
2015-01-21 18:06:59 +00:00
return ExecutionPrivileges{{Name: "", Privilege: ReadPrivilege}}
2015-01-19 20:12:48 +00:00
}
// DropSeriesStatement represents a command for removing a series from the database.
type DropSeriesStatement struct {
2015-02-17 23:29:25 +00:00
// The Id of the series being dropped (optional)
SeriesID uint64
2015-02-17 23:29:25 +00:00
// Data source that fields are extracted from (optional)
Source Source
// An expression evaluated on data point (optional)
Condition Expr
}
// String returns a string representation of the drop series statement.
2015-02-17 23:29:25 +00:00
func (s *DropSeriesStatement) String() string {
var buf bytes.Buffer
i, _ := buf.WriteString("DROP SERIES")
2015-02-17 23:29:25 +00:00
if s.Source != nil {
_, _ = buf.WriteString(" FROM ")
2015-02-17 23:29:25 +00:00
_, _ = buf.WriteString(s.Source.String())
}
if s.Condition != nil {
_, _ = buf.WriteString(" WHERE ")
_, _ = buf.WriteString(s.Condition.String())
}
// If we haven't written any data since the initial statement, then this was a SeriesID statement
if len(buf.String()) == i {
_, _ = buf.WriteString(fmt.Sprintf(" %d", s.SeriesID))
2015-02-17 23:29:25 +00:00
}
return buf.String()
}
2015-02-01 18:47:48 +00:00
// RequiredPrivileges returns the privilige reqired to execute a DropSeriesStatement.
2015-01-19 20:12:48 +00:00
func (s DropSeriesStatement) RequiredPrivileges() ExecutionPrivileges {
2015-01-21 18:06:59 +00:00
return ExecutionPrivileges{{Name: "", Privilege: WritePrivilege}}
2015-01-19 20:12:48 +00:00
}
2015-01-26 03:40:50 +00:00
// ShowContinuousQueriesStatement represents a command for listing continuous queries.
type ShowContinuousQueriesStatement struct{}
// String returns a string representation of the list continuous queries statement.
2015-01-26 03:40:50 +00:00
func (s *ShowContinuousQueriesStatement) String() string { return "SHOW CONTINUOUS QUERIES" }
2015-02-01 18:47:48 +00:00
// RequiredPrivileges returns the privilege required to execute a ShowContinuousQueriesStatement.
2015-01-26 03:40:50 +00:00
func (s *ShowContinuousQueriesStatement) RequiredPrivileges() ExecutionPrivileges {
2015-01-21 18:06:59 +00:00
return ExecutionPrivileges{{Name: "", Privilege: ReadPrivilege}}
2015-01-19 20:12:48 +00:00
}
2015-03-10 19:46:05 +00:00
// ShowServersStatement represents a command for listing all servers.
type ShowServersStatement struct{}
// String returns a string representation of the show servers command.
func (s *ShowServersStatement) String() string { return "SHOW SERVERS" }
// RequiredPrivileges returns the privilege required to execute a ShowServersStatement
func (s *ShowServersStatement) RequiredPrivileges() ExecutionPrivileges {
return ExecutionPrivileges{{Name: "", Privilege: AllPrivileges}}
}
2015-01-26 03:40:50 +00:00
// ShowDatabasesStatement represents a command for listing all databases in the cluster.
type ShowDatabasesStatement struct{}
2015-01-09 15:47:57 +00:00
// String returns a string representation of the list databases command.
2015-01-26 03:40:50 +00:00
func (s *ShowDatabasesStatement) String() string { return "SHOW DATABASES" }
2015-01-09 15:47:57 +00:00
2015-02-01 18:47:48 +00:00
// RequiredPrivileges returns the privilege required to execute a ShowDatabasesStatement
2015-01-26 03:40:50 +00:00
func (s *ShowDatabasesStatement) RequiredPrivileges() ExecutionPrivileges {
2015-01-21 18:06:59 +00:00
return ExecutionPrivileges{{Name: "", Privilege: AllPrivileges}}
2015-01-19 20:12:48 +00:00
}
2015-02-01 18:47:48 +00:00
// CreateContinuousQueryStatement represents a command for creating a continuous query.
2014-11-25 04:49:09 +00:00
type CreateContinuousQueryStatement struct {
// Name of the continuous query to be created.
Name string
// Name of the database to create the continuous query on.
Database string
// Source of data (SELECT statement).
2014-11-25 04:49:09 +00:00
Source *SelectStatement
}
// String returns a string representation of the statement.
func (s *CreateContinuousQueryStatement) String() string {
return fmt.Sprintf("CREATE CONTINUOUS QUERY %s ON %s BEGIN %s END", QuoteIdent(s.Name), QuoteIdent(s.Database), s.Source.String())
}
// DefaultDatabase returns the default database from the statement.
func (s *CreateContinuousQueryStatement) DefaultDatabase() string {
return s.Database
}
2015-02-01 18:47:48 +00:00
// RequiredPrivileges returns the privilege required to execute a CreateContinuousQueryStatement.
2015-01-19 20:12:48 +00:00
func (s *CreateContinuousQueryStatement) RequiredPrivileges() ExecutionPrivileges {
2015-01-21 18:06:59 +00:00
ep := ExecutionPrivileges{{Name: s.Database, Privilege: ReadPrivilege}}
// Selecting into a database that's different from the source?
if s.Source.Target.Measurement.Database != "" {
// Change source database privilege requirement to read.
ep[0].Privilege = ReadPrivilege
// Add destination database privilege requirement and set it to write.
p := ExecutionPrivilege{
Name: s.Source.Target.Measurement.Database,
Privilege: WritePrivilege,
}
ep = append(ep, p)
}
return ep
2015-01-19 20:12:48 +00:00
}
2015-02-01 18:47:48 +00:00
// DropContinuousQueryStatement represents a command for removing a continuous query.
type DropContinuousQueryStatement struct {
2015-03-25 00:11:26 +00:00
Name string
Database string
}
// String returns a string representation of the statement.
func (s *DropContinuousQueryStatement) String() string {
return fmt.Sprintf("DROP CONTINUOUS QUERY %s", s.Name)
}
2015-01-19 20:12:48 +00:00
// RequiredPrivileges returns the privilege(s) required to execute a DropContinuousQueryStatement
func (s *DropContinuousQueryStatement) RequiredPrivileges() ExecutionPrivileges {
2015-01-21 18:06:59 +00:00
return ExecutionPrivileges{{Name: "", Privilege: WritePrivilege}}
2015-01-19 20:12:48 +00:00
}
2015-01-26 03:40:50 +00:00
// ShowMeasurementsStatement represents a command for listing measurements.
type ShowMeasurementsStatement struct {
// An expression evaluated on data point.
Condition Expr
// Fields to sort results by
SortFields SortFields
// Maximum number of rows to be returned.
// Unlimited if zero.
Limit int
2015-01-25 20:34:49 +00:00
// Returns rows starting at an offset from the first row.
Offset int
}
// String returns a string representation of the statement.
2015-01-26 03:40:50 +00:00
func (s *ShowMeasurementsStatement) String() string {
2014-12-16 14:06:28 +00:00
var buf bytes.Buffer
2015-01-26 03:40:50 +00:00
_, _ = buf.WriteString("SHOW MEASUREMENTS")
if s.Condition != nil {
_, _ = buf.WriteString(" WHERE ")
_, _ = buf.WriteString(s.Condition.String())
}
if len(s.SortFields) > 0 {
_, _ = buf.WriteString(" ORDER BY ")
_, _ = buf.WriteString(s.SortFields.String())
}
if s.Limit > 0 {
_, _ = buf.WriteString(" LIMIT ")
_, _ = buf.WriteString(strconv.Itoa(s.Limit))
}
2015-01-25 20:34:49 +00:00
if s.Offset > 0 {
_, _ = buf.WriteString(" OFFSET ")
_, _ = buf.WriteString(strconv.Itoa(s.Offset))
}
return buf.String()
}
2015-01-26 03:40:50 +00:00
// RequiredPrivileges returns the privilege(s) required to execute a ShowMeasurementsStatement
func (s *ShowMeasurementsStatement) RequiredPrivileges() ExecutionPrivileges {
2015-01-21 18:06:59 +00:00
return ExecutionPrivileges{{Name: "", Privilege: ReadPrivilege}}
2015-01-19 20:12:48 +00:00
}
2015-02-23 20:51:52 +00:00
// DropMeasurmentStatement represents a command to drop a measurement.
type DropMeasurementStatement struct {
// Name of the measurement to be dropped.
Name string
}
// String returns a string representation of the drop measurement statement.
func (s *DropMeasurementStatement) String() string {
var buf bytes.Buffer
_, _ = buf.WriteString("DROP MEASUREMENT ")
_, _ = buf.WriteString(s.Name)
return buf.String()
}
// RequiredPrivileges returns the privilege(s) required to execute a DropMeasurementStatement
func (s *DropMeasurementStatement) RequiredPrivileges() ExecutionPrivileges {
return ExecutionPrivileges{{Name: "", Privilege: AllPrivileges}}
}
2015-01-26 03:40:50 +00:00
// ShowRetentionPoliciesStatement represents a command for listing retention policies.
type ShowRetentionPoliciesStatement struct {
// Name of the database to list policies for.
Database string
}
2015-01-26 03:40:50 +00:00
// String returns a string representation of a ShowRetentionPoliciesStatement.
func (s *ShowRetentionPoliciesStatement) String() string {
var buf bytes.Buffer
2015-01-26 03:40:50 +00:00
_, _ = buf.WriteString("SHOW RETENTION POLICIES ")
_, _ = buf.WriteString(s.Database)
return buf.String()
}
2015-01-26 03:40:50 +00:00
// RequiredPrivileges returns the privilege(s) required to execute a ShowRetentionPoliciesStatement
func (s *ShowRetentionPoliciesStatement) RequiredPrivileges() ExecutionPrivileges {
2015-01-21 18:06:59 +00:00
return ExecutionPrivileges{{Name: "", Privilege: ReadPrivilege}}
2015-01-19 20:12:48 +00:00
}
2015-03-12 23:07:41 +00:00
// ShowRetentionPoliciesStatement represents a command for displaying stats for a given server.
type ShowStatsStatement struct {
// Hostname or IP of the server for stats.
Host string
}
// String returns a string representation of a ShowStatsStatement.
func (s *ShowStatsStatement) String() string {
var buf bytes.Buffer
_, _ = buf.WriteString("SHOW STATS ")
if s.Host != "" {
_, _ = buf.WriteString(s.Host)
}
return buf.String()
}
// RequiredPrivileges returns the privilege(s) required to execute a ShowStatsStatement
func (s *ShowStatsStatement) RequiredPrivileges() ExecutionPrivileges {
return ExecutionPrivileges{{Name: "", Privilege: AllPrivileges}}
}
2015-03-24 03:13:54 +00:00
// ShowDiagnosticsStatement represents a command for show node diagnostics.
type ShowDiagnosticsStatement struct{}
// String returns a string representation of the ShowDiagnosticsStatement.
func (s *ShowDiagnosticsStatement) String() string { return "SHOW DIAGNOSTICS" }
// RequiredPrivileges returns the privilege required to execute a ShowDiagnosticsStatement
func (s *ShowDiagnosticsStatement) RequiredPrivileges() ExecutionPrivileges {
return ExecutionPrivileges{{Name: "", Privilege: AllPrivileges}}
}
2015-01-26 03:40:50 +00:00
// ShowTagKeysStatement represents a command for listing tag keys.
type ShowTagKeysStatement struct {
// Data source that fields are extracted from.
Source Source
// An expression evaluated on data point.
Condition Expr
// Fields to sort results by
SortFields SortFields
// Maximum number of rows to be returned.
// Unlimited if zero.
Limit int
2015-01-25 20:34:49 +00:00
// Returns rows starting at an offset from the first row.
Offset int
}
// String returns a string representation of the statement.
2015-01-26 03:40:50 +00:00
func (s *ShowTagKeysStatement) String() string {
2014-12-16 14:06:28 +00:00
var buf bytes.Buffer
2015-01-26 03:40:50 +00:00
_, _ = buf.WriteString("SHOW TAG KEYS")
if s.Source != nil {
_, _ = buf.WriteString(" FROM ")
_, _ = buf.WriteString(s.Source.String())
}
if s.Condition != nil {
_, _ = buf.WriteString(" WHERE ")
_, _ = buf.WriteString(s.Condition.String())
}
if len(s.SortFields) > 0 {
_, _ = buf.WriteString(" ORDER BY ")
_, _ = buf.WriteString(s.SortFields.String())
}
if s.Limit > 0 {
_, _ = buf.WriteString(" LIMIT ")
_, _ = buf.WriteString(strconv.Itoa(s.Limit))
}
2015-01-25 20:34:49 +00:00
if s.Offset > 0 {
_, _ = buf.WriteString(" OFFSET ")
_, _ = buf.WriteString(strconv.Itoa(s.Offset))
}
return buf.String()
}
2015-01-26 03:40:50 +00:00
// RequiredPrivileges returns the privilege(s) required to execute a ShowTagKeysStatement
func (s *ShowTagKeysStatement) RequiredPrivileges() ExecutionPrivileges {
2015-01-21 18:06:59 +00:00
return ExecutionPrivileges{{Name: "", Privilege: ReadPrivilege}}
2015-01-19 20:12:48 +00:00
}
2015-01-26 03:40:50 +00:00
// ShowTagValuesStatement represents a command for listing tag values.
type ShowTagValuesStatement struct {
// Data source that fields are extracted from.
Source Source
// Tag key(s) to pull values from.
TagKeys []string
// An expression evaluated on data point.
Condition Expr
// Fields to sort results by
SortFields SortFields
// Maximum number of rows to be returned.
// Unlimited if zero.
Limit int
2015-01-25 20:34:49 +00:00
// Returns rows starting at an offset from the first row.
Offset int
}
// String returns a string representation of the statement.
2015-01-26 03:40:50 +00:00
func (s *ShowTagValuesStatement) String() string {
2014-12-16 14:06:28 +00:00
var buf bytes.Buffer
2015-01-26 03:40:50 +00:00
_, _ = buf.WriteString("SHOW TAG VALUES")
if s.Source != nil {
_, _ = buf.WriteString(" FROM ")
_, _ = buf.WriteString(s.Source.String())
}
if s.Condition != nil {
_, _ = buf.WriteString(" WHERE ")
_, _ = buf.WriteString(s.Condition.String())
}
if len(s.SortFields) > 0 {
_, _ = buf.WriteString(" ORDER BY ")
_, _ = buf.WriteString(s.SortFields.String())
}
if s.Limit > 0 {
_, _ = buf.WriteString(" LIMIT ")
_, _ = buf.WriteString(strconv.Itoa(s.Limit))
}
2015-01-25 20:34:49 +00:00
if s.Offset > 0 {
_, _ = buf.WriteString(" OFFSET ")
_, _ = buf.WriteString(strconv.Itoa(s.Offset))
}
return buf.String()
}
2015-01-26 03:40:50 +00:00
// RequiredPrivileges returns the privilege(s) required to execute a ShowTagValuesStatement
func (s *ShowTagValuesStatement) RequiredPrivileges() ExecutionPrivileges {
2015-01-21 18:06:59 +00:00
return ExecutionPrivileges{{Name: "", Privilege: ReadPrivilege}}
2015-01-19 20:12:48 +00:00
}
2015-01-26 03:40:50 +00:00
// ShowUsersStatement represents a command for listing users.
type ShowUsersStatement struct{}
2015-01-14 16:53:17 +00:00
2015-01-26 03:40:50 +00:00
// String retuns a string representation of the ShowUsersStatement.
func (s *ShowUsersStatement) String() string {
return "SHOW USERS"
2015-01-14 16:53:17 +00:00
}
2015-01-26 03:40:50 +00:00
// RequiredPrivileges returns the privilege(s) required to execute a ShowUsersStatement
func (s *ShowUsersStatement) RequiredPrivileges() ExecutionPrivileges {
2015-01-21 18:06:59 +00:00
return ExecutionPrivileges{{Name: "", Privilege: AllPrivileges}}
2015-01-19 20:12:48 +00:00
}
2015-02-01 18:47:48 +00:00
// ShowFieldKeysStatement represents a command for listing field keys.
2015-01-26 03:40:50 +00:00
type ShowFieldKeysStatement struct {
// Data source that fields are extracted from.
Source Source
// Fields to sort results by
SortFields SortFields
// Maximum number of rows to be returned.
// Unlimited if zero.
Limit int
2015-01-25 20:34:49 +00:00
// Returns rows starting at an offset from the first row.
Offset int
}
// String returns a string representation of the statement.
2015-01-26 03:40:50 +00:00
func (s *ShowFieldKeysStatement) String() string {
2014-12-16 14:06:28 +00:00
var buf bytes.Buffer
2015-01-26 03:40:50 +00:00
_, _ = buf.WriteString("SHOW FIELD KEYS")
if s.Source != nil {
_, _ = buf.WriteString(" FROM ")
_, _ = buf.WriteString(s.Source.String())
}
if len(s.SortFields) > 0 {
_, _ = buf.WriteString(" ORDER BY ")
_, _ = buf.WriteString(s.SortFields.String())
}
if s.Limit > 0 {
_, _ = buf.WriteString(" LIMIT ")
_, _ = buf.WriteString(strconv.Itoa(s.Limit))
}
2015-01-25 20:34:49 +00:00
if s.Offset > 0 {
_, _ = buf.WriteString(" OFFSET ")
_, _ = buf.WriteString(strconv.Itoa(s.Offset))
}
return buf.String()
}
2015-01-26 03:40:50 +00:00
// RequiredPrivileges returns the privilege(s) required to execute a ShowFieldKeysStatement
func (s *ShowFieldKeysStatement) RequiredPrivileges() ExecutionPrivileges {
2015-01-21 18:06:59 +00:00
return ExecutionPrivileges{{Name: "", Privilege: ReadPrivilege}}
2015-01-19 20:12:48 +00:00
}
2014-11-15 19:04:30 +00:00
// Fields represents a list of fields.
type Fields []*Field
// String returns a string representation of the fields.
func (a Fields) String() string {
var str []string
for _, f := range a {
str = append(str, f.String())
}
return strings.Join(str, ", ")
}
2014-11-22 04:12:48 +00:00
// Field represents an expression retrieved from a select statement.
2014-11-15 19:04:30 +00:00
type Field struct {
Expr Expr
Alias string
2014-12-08 05:08:39 +00:00
}
// Name returns the name of the field. Returns alias, if set.
// Otherwise uses the function name or variable name.
func (f *Field) Name() string {
// Return alias, if set.
if f.Alias != "" {
return f.Alias
}
// Return the function name or variable name, if available.
switch expr := f.Expr.(type) {
case *Call:
return expr.Name
case *VarRef:
return expr.Val
}
// Otherwise return a blank name.
return ""
2014-11-15 19:04:30 +00:00
}
// String returns a string representation of the field.
func (f *Field) String() string {
if f.Alias == "" {
return f.Expr.String()
}
return fmt.Sprintf("%s AS %s", f.Expr.String(), f.Alias)
}
2015-03-13 22:52:49 +00:00
// Sort Interface for Fields
func (f Fields) Len() int { return len(f) }
func (f Fields) Less(i, j int) bool { return f[i].Name() < f[j].Name() }
func (f Fields) Swap(i, j int) { f[i], f[j] = f[j], f[i] }
2014-11-15 19:04:30 +00:00
// Dimensions represents a list of dimensions.
type Dimensions []*Dimension
// String returns a string representation of the dimensions.
func (a Dimensions) String() string {
var str []string
for _, d := range a {
str = append(str, d.String())
}
return strings.Join(str, ", ")
}
2015-01-23 09:44:56 +00:00
// Normalize returns the interval and tag dimensions separately.
// Returns 0 if no time interval is specified.
// Returns an error if multiple time dimensions exist or if non-VarRef dimensions are specified.
func (a Dimensions) Normalize() (time.Duration, []string, error) {
var dur time.Duration
var tags []string
for _, dim := range a {
switch expr := dim.Expr.(type) {
case *Call:
// Ensure the call is time() and it only has one duration argument.
// If we already have a duration
2015-05-01 15:29:39 +00:00
if expr.Name != "time" {
2015-01-23 09:44:56 +00:00
return 0, nil, errors.New("only time() calls allowed in dimensions")
} else if len(expr.Args) != 1 {
return 0, nil, errors.New("time dimension expected one argument")
} else if lit, ok := expr.Args[0].(*DurationLiteral); !ok {
return 0, nil, errors.New("time dimension must have one duration argument")
} else if dur != 0 {
return 0, nil, errors.New("multiple time dimensions not allowed")
} else {
dur = lit.Val
}
case *VarRef:
tags = append(tags, expr.Val)
default:
return 0, nil, errors.New("only time and tag dimensions allowed")
}
}
return dur, tags, nil
}
2014-11-22 04:12:48 +00:00
// Dimension represents an expression that a select statement is grouped by.
2014-11-15 19:04:30 +00:00
type Dimension struct {
2014-11-22 04:12:48 +00:00
Expr Expr
2014-11-15 19:04:30 +00:00
}
// String returns a string representation of the dimension.
func (d *Dimension) String() string { return d.Expr.String() }
// Measurements represents a list of measurements.
type Measurements []*Measurement
// String returns a string representation of the measurements.
func (a Measurements) String() string {
var str []string
for _, m := range a {
str = append(str, m.String())
}
return strings.Join(str, ", ")
}
// Measurement represents a single measurement used as a datasource.
type Measurement struct {
Database string
RetentionPolicy string
Name string
Regex *RegexLiteral
2014-11-15 19:04:30 +00:00
}
// String returns a string representation of the measurement.
2015-03-06 13:52:25 +00:00
func (m *Measurement) String() string {
var buf bytes.Buffer
if m.Database != "" {
_, _ = buf.WriteString(`"`)
_, _ = buf.WriteString(m.Database)
_, _ = buf.WriteString(`".`)
2015-03-06 13:52:25 +00:00
}
if m.RetentionPolicy != "" {
_, _ = buf.WriteString(`"`)
_, _ = buf.WriteString(m.RetentionPolicy)
_, _ = buf.WriteString(`"`)
}
if m.Database != "" || m.RetentionPolicy != "" {
_, _ = buf.WriteString(`.`)
}
2014-11-15 19:04:30 +00:00
if m.Name != "" {
_, _ = buf.WriteString(QuoteIdent(m.Name))
} else if m.Regex != nil {
_, _ = buf.WriteString(m.Regex.String())
}
return buf.String()
2014-11-15 19:04:30 +00:00
}
2014-11-22 04:12:48 +00:00
// VarRef represents a reference to a variable.
2014-11-15 19:04:30 +00:00
type VarRef struct {
Val string
}
// String returns a string representation of the variable reference.
func (r *VarRef) String() string { return r.Val }
2014-11-15 19:04:30 +00:00
// Call represents a function call.
type Call struct {
Name string
2014-11-25 03:43:23 +00:00
Args []Expr
2014-11-15 19:04:30 +00:00
}
// String returns a string representation of the call.
func (c *Call) String() string {
// Join arguments.
var str []string
for _, arg := range c.Args {
str = append(str, arg.String())
}
// Write function name and args.
return fmt.Sprintf("%s(%s)", c.Name, strings.Join(str, ", "))
}
// Distinct represents a DISTINCT expression.
type Distinct struct {
// Identifier following DISTINCT
Val string
}
// String returns a string representation of the expression.
func (d *Distinct) String() string {
return fmt.Sprintf("DISTINCT %s", d.Val)
}
// NewCall returns a new call expression from this expressions.
func (d *Distinct) NewCall() *Call {
return &Call{
Name: "distinct",
Args: []Expr{
&VarRef{Val: d.Val},
},
}
}
2014-11-22 04:12:48 +00:00
// NumberLiteral represents a numeric literal.
type NumberLiteral struct {
2014-11-15 19:04:30 +00:00
Val float64
}
// String returns a string representation of the literal.
func (l *NumberLiteral) String() string { return strconv.FormatFloat(l.Val, 'f', 3, 64) }
2014-11-22 04:12:48 +00:00
// BooleanLiteral represents a boolean literal.
2014-11-15 19:04:30 +00:00
type BooleanLiteral struct {
Val bool
}
// String returns a string representation of the literal.
func (l *BooleanLiteral) String() string {
if l.Val {
return "true"
}
return "false"
}
2015-01-23 09:44:56 +00:00
// isTrueLiteral returns true if the expression is a literal "true" value.
func isTrueLiteral(expr Expr) bool {
if expr, ok := expr.(*BooleanLiteral); ok {
return expr.Val == true
}
return false
}
// isFalseLiteral returns true if the expression is a literal "false" value.
func isFalseLiteral(expr Expr) bool {
if expr, ok := expr.(*BooleanLiteral); ok {
return expr.Val == false
}
return false
}
2014-11-22 04:12:48 +00:00
// StringLiteral represents a string literal.
2014-11-15 19:04:30 +00:00
type StringLiteral struct {
Val string
}
// String returns a string representation of the literal.
func (l *StringLiteral) String() string { return QuoteString(l.Val) }
2014-11-22 04:12:48 +00:00
// TimeLiteral represents a point-in-time literal.
2014-11-15 19:04:30 +00:00
type TimeLiteral struct {
Val time.Time
}
// String returns a string representation of the literal.
2014-12-11 06:32:45 +00:00
func (l *TimeLiteral) String() string {
return `"` + l.Val.UTC().Format(DateTimeFormat) + `"`
2014-12-11 06:32:45 +00:00
}
2014-11-22 04:12:48 +00:00
// DurationLiteral represents a duration literal.
2014-11-15 19:04:30 +00:00
type DurationLiteral struct {
Val time.Duration
}
// String returns a string representation of the literal.
func (l *DurationLiteral) String() string { return FormatDuration(l.Val) }
2015-01-23 09:44:56 +00:00
// nilLiteral represents a nil literal.
// This is not available to the query language itself. It's only used internally.
type nilLiteral struct{}
// String returns a string representation of the literal.
func (l *nilLiteral) String() string { return `nil` }
2014-11-15 19:04:30 +00:00
// BinaryExpr represents an operation between two expressions.
type BinaryExpr struct {
Op Token
LHS Expr
RHS Expr
}
// String returns a string representation of the binary expression.
func (e *BinaryExpr) String() string {
return fmt.Sprintf("%s %s %s", e.LHS.String(), e.Op.String(), e.RHS.String())
}
2014-11-25 06:12:32 +00:00
// ParenExpr represents a parenthesized expression.
type ParenExpr struct {
Expr Expr
}
// String returns a string representation of the parenthesized expression.
func (e *ParenExpr) String() string { return fmt.Sprintf("(%s)", e.Expr.String()) }
// RegexLiteral represents a regular expression.
type RegexLiteral struct {
Val *regexp.Regexp
}
// String returns a string representation of the literal.
2015-03-06 13:52:25 +00:00
func (r *RegexLiteral) String() string {
if r.Val != nil {
return fmt.Sprintf("/%s/", r.Val.String())
}
return ""
}
// CloneRegexLiteral returns a clone of the RegexLiteral.
func CloneRegexLiteral(r *RegexLiteral) *RegexLiteral {
if r == nil {
return nil
}
clone := &RegexLiteral{}
if r.Val != nil {
clone.Val = regexp.MustCompile(r.Val.String())
}
return clone
}
2014-11-25 23:23:10 +00:00
// Wildcard represents a wild card expression.
type Wildcard struct{}
// String returns a string representation of the wildcard.
func (e *Wildcard) String() string { return "*" }
2014-11-25 22:43:22 +00:00
2015-01-23 09:44:56 +00:00
// CloneExpr returns a deep copy of the expression.
func CloneExpr(expr Expr) Expr {
if expr == nil {
return nil
}
2014-12-11 06:32:45 +00:00
switch expr := expr.(type) {
case *BinaryExpr:
2015-01-23 09:44:56 +00:00
return &BinaryExpr{Op: expr.Op, LHS: CloneExpr(expr.LHS), RHS: CloneExpr(expr.RHS)}
2014-12-11 06:32:45 +00:00
case *BooleanLiteral:
2015-01-23 09:44:56 +00:00
return &BooleanLiteral{Val: expr.Val}
case *Call:
args := make([]Expr, len(expr.Args))
for i, arg := range expr.Args {
args[i] = CloneExpr(arg)
2014-12-11 06:32:45 +00:00
}
2015-01-23 09:44:56 +00:00
return &Call{Name: expr.Name, Args: args}
case *Distinct:
return &Distinct{Val: expr.Val}
2014-12-11 06:32:45 +00:00
case *DurationLiteral:
2015-01-23 09:44:56 +00:00
return &DurationLiteral{Val: expr.Val}
case *NumberLiteral:
return &NumberLiteral{Val: expr.Val}
case *ParenExpr:
return &ParenExpr{Expr: CloneExpr(expr.Expr)}
2015-02-16 20:30:58 +00:00
case *RegexLiteral:
return &RegexLiteral{Val: expr.Val}
2014-12-11 06:32:45 +00:00
case *StringLiteral:
2015-01-23 09:44:56 +00:00
return &StringLiteral{Val: expr.Val}
case *TimeLiteral:
return &TimeLiteral{Val: expr.Val}
case *VarRef:
return &VarRef{Val: expr.Val}
case *Wildcard:
return &Wildcard{}
2014-12-11 06:32:45 +00:00
}
2015-01-23 09:44:56 +00:00
panic("unreachable")
2014-12-11 06:32:45 +00:00
}
// TimeRange returns the minimum and maximum times specified by an expression.
2014-12-16 15:50:30 +00:00
// Returns zero times if there is no bound.
func TimeRange(expr Expr) (min, max time.Time) {
WalkFunc(expr, func(n Node) {
if n, ok := n.(*BinaryExpr); ok {
// Extract literal expression & operator on LHS.
// Check for "time" on the left-hand side first.
// Otherwise check for for the right-hand side and flip the operator.
value, op := timeExprValue(n.LHS, n.RHS), n.Op
if value.IsZero() {
if value = timeExprValue(n.RHS, n.LHS); value.IsZero() {
return
} else if op == LT {
op = GT
} else if op == LTE {
op = GTE
} else if op == GT {
op = LT
} else if op == GTE {
op = LTE
}
}
// Update the min/max depending on the operator.
// The GT & LT update the value by +/- 1µs not make them "not equal".
switch op {
case GT:
if min.IsZero() || value.After(min) {
min = value.Add(time.Microsecond)
}
case GTE:
if min.IsZero() || value.After(min) {
min = value
}
case LT:
if max.IsZero() || value.Before(max) {
max = value.Add(-time.Microsecond)
}
case LTE:
if max.IsZero() || value.Before(max) {
max = value
}
case EQ:
if min.IsZero() || value.After(min) {
min = value
}
if max.IsZero() || value.Before(max) {
max = value
}
}
}
})
return
}
// timeExprValue returns the time literal value of a "time == <TimeLiteral>" expression.
// Returns zero time if the expression is not a time expression.
func timeExprValue(ref Expr, lit Expr) time.Time {
if ref, ok := ref.(*VarRef); ok && strings.ToLower(ref.Val) == "time" {
switch lit := lit.(type) {
case *TimeLiteral:
return lit.Val
case *DurationLiteral:
return time.Unix(0, int64(lit.Val)).UTC()
}
}
return time.Time{}
}
2014-12-21 22:18:55 +00:00
// Visitor can be called by Walk to traverse an AST hierarchy.
// The Visit() function is called once per node.
type Visitor interface {
Visit(Node) Visitor
}
2014-11-15 19:04:30 +00:00
// Walk traverses a node hierarchy in depth-first order.
func Walk(v Visitor, node Node) {
if node == nil {
return
}
2014-11-15 19:04:30 +00:00
if v = v.Visit(node); v == nil {
return
}
switch n := node.(type) {
case *BinaryExpr:
Walk(v, n.LHS)
Walk(v, n.RHS)
2014-11-22 04:12:48 +00:00
case *Call:
for _, expr := range n.Args {
Walk(v, expr)
}
case *CreateContinuousQueryStatement:
Walk(v, n.Source)
case *Dimension:
Walk(v, n.Expr)
case Dimensions:
for _, c := range n {
Walk(v, c)
}
case *Field:
Walk(v, n.Expr)
case Fields:
for _, c := range n {
Walk(v, c)
2014-11-15 19:04:30 +00:00
}
case *ParenExpr:
Walk(v, n.Expr)
case *Query:
Walk(v, n.Statements)
2014-11-22 04:12:48 +00:00
case *SelectStatement:
Walk(v, n.Fields)
Walk(v, n.Target)
2014-11-22 04:12:48 +00:00
Walk(v, n.Dimensions)
2015-03-06 13:52:25 +00:00
Walk(v, n.Sources)
2014-11-22 04:12:48 +00:00
Walk(v, n.Condition)
Walk(v, n.SortFields)
2014-11-22 04:12:48 +00:00
2015-01-28 04:36:19 +00:00
case *ShowSeriesStatement:
Walk(v, n.Source)
Walk(v, n.Condition)
2015-01-29 01:26:15 +00:00
case *ShowTagKeysStatement:
Walk(v, n.Source)
Walk(v, n.Condition)
Walk(v, n.SortFields)
case *ShowTagValuesStatement:
Walk(v, n.Source)
Walk(v, n.Condition)
Walk(v, n.SortFields)
case SortFields:
for _, sf := range n {
Walk(v, sf)
}
2015-03-13 22:35:36 +00:00
case Sources:
for _, s := range n {
Walk(v, s)
}
case Statements:
for _, s := range n {
Walk(v, s)
2014-11-15 19:04:30 +00:00
}
case *Target:
if n != nil {
Walk(v, n.Measurement)
2014-11-25 03:43:23 +00:00
}
2014-11-15 19:04:30 +00:00
}
}
// WalkFunc traverses a node hierarchy in depth-first order.
func WalkFunc(node Node, fn func(Node)) {
Walk(walkFuncVisitor(fn), node)
}
type walkFuncVisitor func(Node)
func (fn walkFuncVisitor) Visit(n Node) Visitor { fn(n); return fn }
2014-12-21 22:18:55 +00:00
// Rewriter can be called by Rewrite to replace nodes in the AST hierarchy.
// The Rewrite() function is called once per node.
type Rewriter interface {
Rewrite(Node) Node
}
// Rewrite recursively invokes the rewriter to replace each node.
// Nodes are traversed depth-first and rewritten from leaf to root.
func Rewrite(r Rewriter, node Node) Node {
switch n := node.(type) {
case *Query:
n.Statements = Rewrite(r, n.Statements).(Statements)
case Statements:
for i, s := range n {
n[i] = Rewrite(r, s).(Statement)
}
case *SelectStatement:
n.Fields = Rewrite(r, n.Fields).(Fields)
n.Dimensions = Rewrite(r, n.Dimensions).(Dimensions)
2015-03-06 13:52:25 +00:00
n.Sources = Rewrite(r, n.Sources).(Sources)
2014-12-21 22:18:55 +00:00
n.Condition = Rewrite(r, n.Condition).(Expr)
case Fields:
for i, f := range n {
n[i] = Rewrite(r, f).(*Field)
}
case *Field:
n.Expr = Rewrite(r, n.Expr).(Expr)
case Dimensions:
for i, d := range n {
n[i] = Rewrite(r, d).(*Dimension)
}
case *Dimension:
n.Expr = Rewrite(r, n.Expr).(Expr)
case *BinaryExpr:
n.LHS = Rewrite(r, n.LHS).(Expr)
n.RHS = Rewrite(r, n.RHS).(Expr)
case *ParenExpr:
n.Expr = Rewrite(r, n.Expr).(Expr)
case *Call:
for i, expr := range n.Args {
n.Args[i] = Rewrite(r, expr).(Expr)
}
}
return r.Rewrite(node)
}
// RewriteFunc rewrites a node hierarchy.
func RewriteFunc(node Node, fn func(Node) Node) Node {
return Rewrite(rewriterFunc(fn), node)
}
type rewriterFunc func(Node) Node
func (fn rewriterFunc) Rewrite(n Node) Node { return fn(n) }
2015-01-23 09:44:56 +00:00
2015-01-28 00:20:34 +00:00
// Eval evaluates expr against a map.
func Eval(expr Expr, m map[string]interface{}) interface{} {
if expr == nil {
return nil
}
switch expr := expr.(type) {
case *BinaryExpr:
return evalBinaryExpr(expr, m)
case *BooleanLiteral:
return expr.Val
case *NumberLiteral:
return expr.Val
case *ParenExpr:
return Eval(expr.Expr, m)
case *StringLiteral:
return expr.Val
case *VarRef:
return m[expr.Val]
default:
return nil
}
}
func evalBinaryExpr(expr *BinaryExpr, m map[string]interface{}) interface{} {
lhs := Eval(expr.LHS, m)
rhs := Eval(expr.RHS, m)
// Evaluate if both sides are simple types.
switch lhs := lhs.(type) {
case bool:
rhs, _ := rhs.(bool)
switch expr.Op {
case AND:
return lhs && rhs
case OR:
return lhs || rhs
}
case float64:
rhs, _ := rhs.(float64)
switch expr.Op {
case EQ:
return lhs == rhs
case NEQ:
return lhs != rhs
case LT:
return lhs < rhs
case LTE:
return lhs <= rhs
case GT:
return lhs > rhs
case GTE:
return lhs >= rhs
case ADD:
return lhs + rhs
case SUB:
return lhs - rhs
case MUL:
return lhs * rhs
case DIV:
if rhs == 0 {
return float64(0)
}
return lhs / rhs
}
case string:
rhs, _ := rhs.(string)
switch expr.Op {
case EQ:
return lhs == rhs
case NEQ:
return lhs != rhs
}
}
return nil
}
2015-01-23 09:44:56 +00:00
// Reduce evaluates expr using the available values in valuer.
// References that don't exist in valuer are ignored.
func Reduce(expr Expr, valuer Valuer) Expr {
expr = reduce(expr, valuer)
// Unwrap parens at top level.
if expr, ok := expr.(*ParenExpr); ok {
return expr.Expr
}
return expr
}
func reduce(expr Expr, valuer Valuer) Expr {
if expr == nil {
return nil
}
switch expr := expr.(type) {
case *BinaryExpr:
return reduceBinaryExpr(expr, valuer)
case *Call:
return reduceCall(expr, valuer)
case *ParenExpr:
return reduceParenExpr(expr, valuer)
case *VarRef:
return reduceVarRef(expr, valuer)
default:
return CloneExpr(expr)
}
}
func reduceBinaryExpr(expr *BinaryExpr, valuer Valuer) Expr {
// Reduce both sides first.
op := expr.Op
lhs := reduce(expr.LHS, valuer)
rhs := reduce(expr.RHS, valuer)
// Do not evaluate if one side is nil.
if lhs == nil || rhs == nil {
return &BinaryExpr{LHS: lhs, RHS: rhs, Op: expr.Op}
}
// If we have a logical operator (AND, OR) and one side is a boolean literal
// then we need to have special handling.
if op == AND {
if isFalseLiteral(lhs) || isFalseLiteral(rhs) {
return &BooleanLiteral{Val: false}
} else if isTrueLiteral(lhs) {
return rhs
} else if isTrueLiteral(rhs) {
return lhs
}
} else if op == OR {
if isTrueLiteral(lhs) || isTrueLiteral(rhs) {
return &BooleanLiteral{Val: true}
} else if isFalseLiteral(lhs) {
return rhs
} else if isFalseLiteral(rhs) {
return lhs
}
}
// Evaluate if both sides are simple types.
switch lhs := lhs.(type) {
case *BooleanLiteral:
return reduceBinaryExprBooleanLHS(op, lhs, rhs)
case *DurationLiteral:
return reduceBinaryExprDurationLHS(op, lhs, rhs)
case *nilLiteral:
return reduceBinaryExprNilLHS(op, lhs, rhs)
case *NumberLiteral:
return reduceBinaryExprNumberLHS(op, lhs, rhs)
case *StringLiteral:
return reduceBinaryExprStringLHS(op, lhs, rhs)
case *TimeLiteral:
return reduceBinaryExprTimeLHS(op, lhs, rhs)
default:
return &BinaryExpr{Op: op, LHS: lhs, RHS: rhs}
}
}
func reduceBinaryExprBooleanLHS(op Token, lhs *BooleanLiteral, rhs Expr) Expr {
switch rhs := rhs.(type) {
case *BooleanLiteral:
switch op {
case EQ:
return &BooleanLiteral{Val: lhs.Val == rhs.Val}
case NEQ:
return &BooleanLiteral{Val: lhs.Val != rhs.Val}
case AND:
return &BooleanLiteral{Val: lhs.Val && rhs.Val}
case OR:
return &BooleanLiteral{Val: lhs.Val || rhs.Val}
}
case *nilLiteral:
return &BooleanLiteral{Val: false}
}
return &BinaryExpr{Op: op, LHS: lhs, RHS: rhs}
}
func reduceBinaryExprDurationLHS(op Token, lhs *DurationLiteral, rhs Expr) Expr {
switch rhs := rhs.(type) {
case *DurationLiteral:
switch op {
case ADD:
return &DurationLiteral{Val: lhs.Val + rhs.Val}
case SUB:
return &DurationLiteral{Val: lhs.Val - rhs.Val}
case EQ:
return &BooleanLiteral{Val: lhs.Val == rhs.Val}
case NEQ:
return &BooleanLiteral{Val: lhs.Val != rhs.Val}
case GT:
return &BooleanLiteral{Val: lhs.Val > rhs.Val}
case GTE:
return &BooleanLiteral{Val: lhs.Val >= rhs.Val}
case LT:
return &BooleanLiteral{Val: lhs.Val < rhs.Val}
case LTE:
return &BooleanLiteral{Val: lhs.Val <= rhs.Val}
}
case *NumberLiteral:
switch op {
case MUL:
return &DurationLiteral{Val: lhs.Val * time.Duration(rhs.Val)}
case DIV:
if rhs.Val == 0 {
return &DurationLiteral{Val: 0}
}
return &DurationLiteral{Val: lhs.Val / time.Duration(rhs.Val)}
}
case *TimeLiteral:
switch op {
case ADD:
return &TimeLiteral{Val: rhs.Val.Add(lhs.Val)}
}
case *nilLiteral:
return &BooleanLiteral{Val: false}
}
return &BinaryExpr{Op: op, LHS: lhs, RHS: rhs}
}
func reduceBinaryExprNilLHS(op Token, lhs *nilLiteral, rhs Expr) Expr {
switch op {
case EQ, NEQ:
return &BooleanLiteral{Val: false}
}
return &BinaryExpr{Op: op, LHS: lhs, RHS: rhs}
}
func reduceBinaryExprNumberLHS(op Token, lhs *NumberLiteral, rhs Expr) Expr {
switch rhs := rhs.(type) {
case *NumberLiteral:
switch op {
case ADD:
return &NumberLiteral{Val: lhs.Val + rhs.Val}
case SUB:
return &NumberLiteral{Val: lhs.Val - rhs.Val}
case MUL:
return &NumberLiteral{Val: lhs.Val * rhs.Val}
case DIV:
if rhs.Val == 0 {
return &NumberLiteral{Val: 0}
}
return &NumberLiteral{Val: lhs.Val / rhs.Val}
case EQ:
return &BooleanLiteral{Val: lhs.Val == rhs.Val}
case NEQ:
return &BooleanLiteral{Val: lhs.Val != rhs.Val}
case GT:
return &BooleanLiteral{Val: lhs.Val > rhs.Val}
case GTE:
return &BooleanLiteral{Val: lhs.Val >= rhs.Val}
case LT:
return &BooleanLiteral{Val: lhs.Val < rhs.Val}
case LTE:
return &BooleanLiteral{Val: lhs.Val <= rhs.Val}
}
case *nilLiteral:
return &BooleanLiteral{Val: false}
}
return &BinaryExpr{Op: op, LHS: lhs, RHS: rhs}
}
func reduceBinaryExprStringLHS(op Token, lhs *StringLiteral, rhs Expr) Expr {
switch rhs := rhs.(type) {
case *StringLiteral:
switch op {
case EQ:
return &BooleanLiteral{Val: lhs.Val == rhs.Val}
case NEQ:
return &BooleanLiteral{Val: lhs.Val != rhs.Val}
case ADD:
return &StringLiteral{Val: lhs.Val + rhs.Val}
}
case *nilLiteral:
switch op {
case EQ, NEQ:
return &BooleanLiteral{Val: false}
}
}
return &BinaryExpr{Op: op, LHS: lhs, RHS: rhs}
}
func reduceBinaryExprTimeLHS(op Token, lhs *TimeLiteral, rhs Expr) Expr {
switch rhs := rhs.(type) {
case *DurationLiteral:
switch op {
case ADD:
return &TimeLiteral{Val: lhs.Val.Add(rhs.Val)}
case SUB:
return &TimeLiteral{Val: lhs.Val.Add(-rhs.Val)}
}
case *TimeLiteral:
switch op {
case SUB:
return &DurationLiteral{Val: lhs.Val.Sub(rhs.Val)}
case EQ:
return &BooleanLiteral{Val: lhs.Val.Equal(rhs.Val)}
case NEQ:
return &BooleanLiteral{Val: !lhs.Val.Equal(rhs.Val)}
case GT:
return &BooleanLiteral{Val: lhs.Val.After(rhs.Val)}
case GTE:
return &BooleanLiteral{Val: lhs.Val.After(rhs.Val) || lhs.Val.Equal(rhs.Val)}
case LT:
return &BooleanLiteral{Val: lhs.Val.Before(rhs.Val)}
case LTE:
return &BooleanLiteral{Val: lhs.Val.Before(rhs.Val) || lhs.Val.Equal(rhs.Val)}
}
case *nilLiteral:
return &BooleanLiteral{Val: false}
}
return &BinaryExpr{Op: op, LHS: lhs, RHS: rhs}
}
func reduceCall(expr *Call, valuer Valuer) Expr {
// Evaluate "now()" if valuer is set.
2015-05-01 15:29:39 +00:00
if expr.Name == "now" && len(expr.Args) == 0 && valuer != nil {
2015-01-23 09:44:56 +00:00
if v, ok := valuer.Value("now()"); ok {
v, _ := v.(time.Time)
return &TimeLiteral{Val: v}
}
}
// Otherwise reduce arguments.
args := make([]Expr, len(expr.Args))
for i, arg := range expr.Args {
args[i] = reduce(arg, valuer)
}
return &Call{Name: expr.Name, Args: args}
}
func reduceParenExpr(expr *ParenExpr, valuer Valuer) Expr {
subexpr := reduce(expr.Expr, valuer)
if subexpr, ok := subexpr.(*BinaryExpr); ok {
return &ParenExpr{Expr: subexpr}
}
return subexpr
}
func reduceVarRef(expr *VarRef, valuer Valuer) Expr {
// Ignore if there is no valuer.
if valuer == nil {
return &VarRef{Val: expr.Val}
}
// Retrieve the value of the ref.
// Ignore if the value doesn't exist.
v, ok := valuer.Value(expr.Val)
if !ok {
return &VarRef{Val: expr.Val}
}
// Return the value as a literal.
switch v := v.(type) {
case bool:
return &BooleanLiteral{Val: v}
case time.Duration:
return &DurationLiteral{Val: v}
case float64:
return &NumberLiteral{Val: v}
case string:
return &StringLiteral{Val: v}
case time.Time:
return &TimeLiteral{Val: v}
default:
return &nilLiteral{}
}
}
// Valuer is the interface that wraps the Value() method.
//
// Value returns the value and existence flag for a given key.
type Valuer interface {
Value(key string) (interface{}, bool)
}
// nowValuer returns only the value for "now()".
2015-04-15 15:26:36 +00:00
type NowValuer struct {
2015-01-23 09:44:56 +00:00
Now time.Time
}
2015-04-15 15:26:36 +00:00
func (v *NowValuer) Value(key string) (interface{}, bool) {
2015-01-23 09:44:56 +00:00
if key == "now()" {
return v.Now, true
}
return nil, false
}