influxdb/query/ast/ast.go

851 lines
20 KiB
Go

package ast
import (
"encoding/json"
"fmt"
"regexp"
"time"
)
// Position represents a specific location in the source
type Position struct {
Line int `json:"line"` // Line is the line in the source marked by this position
Column int `json:"column"` // Column is the column in the source marked by this position
}
// SourceLocation represents the location of a node in the AST
type SourceLocation struct {
Start Position `json:"start"` // Start is the location in the source the node starts
End Position `json:"end"` // End is the location in the source the node ends
Source *string `json:"source,omitempty"` // Source is optional raw source
}
// Node represents a node in the InfluxDB abstract syntax tree.
type Node interface {
node()
Type() string // Type property is a string that contains the variant type of the node
Location() *SourceLocation
Copy() Node
// All node must support json marshalling
json.Marshaler
}
func (*Program) node() {}
func (*BlockStatement) node() {}
func (*ExpressionStatement) node() {}
func (*ReturnStatement) node() {}
func (*VariableDeclaration) node() {}
func (*VariableDeclarator) node() {}
func (*ArrayExpression) node() {}
func (*ArrowFunctionExpression) node() {}
func (*BinaryExpression) node() {}
func (*CallExpression) node() {}
func (*ConditionalExpression) node() {}
func (*LogicalExpression) node() {}
func (*MemberExpression) node() {}
func (*PipeExpression) node() {}
func (*ObjectExpression) node() {}
func (*UnaryExpression) node() {}
func (*Property) node() {}
func (*Identifier) node() {}
func (*BooleanLiteral) node() {}
func (*DateTimeLiteral) node() {}
func (*DurationLiteral) node() {}
func (*FloatLiteral) node() {}
func (*IntegerLiteral) node() {}
func (*PipeLiteral) node() {}
func (*RegexpLiteral) node() {}
func (*StringLiteral) node() {}
func (*UnsignedIntegerLiteral) node() {}
// BaseNode holds the attributes every expression or statement should have
type BaseNode struct {
Loc *SourceLocation `json:"location,omitempty"`
}
// Location is the source location of the Node
func (b *BaseNode) Location() *SourceLocation { return b.Loc }
// Program represents a complete program source tree
type Program struct {
*BaseNode
Body []Statement `json:"body"`
}
// Type is the abstract type
func (*Program) Type() string { return "Program" }
func (p *Program) Copy() Node {
np := new(Program)
*np = *p
if len(p.Body) > 0 {
np.Body = make([]Statement, len(p.Body))
for i, s := range p.Body {
np.Body[i] = s.Copy().(Statement)
}
}
return np
}
// Statement Perhaps we don't even want statements nor expression statements
type Statement interface {
Node
stmt()
}
func (*BlockStatement) stmt() {}
func (*ExpressionStatement) stmt() {}
func (*ReturnStatement) stmt() {}
func (*VariableDeclaration) stmt() {}
// BlockStatement is a set of statements
type BlockStatement struct {
*BaseNode
Body []Statement `json:"body"`
}
// Type is the abstract type
func (*BlockStatement) Type() string { return "BlockStatement" }
func (s *BlockStatement) Copy() Node {
ns := new(BlockStatement)
*ns = *s
if len(s.Body) > 0 {
ns.Body = make([]Statement, len(s.Body))
for i, stmt := range s.Body {
ns.Body[i] = stmt.Copy().(Statement)
}
}
return ns
}
// ExpressionStatement may consist of an expression that does not return a value and is executed solely for its side-effects.
type ExpressionStatement struct {
*BaseNode
Expression Expression `json:"expression"`
}
// Type is the abstract type
func (*ExpressionStatement) Type() string { return "ExpressionStatement" }
func (s *ExpressionStatement) Copy() Node {
if s == nil {
return s
}
ns := new(ExpressionStatement)
*ns = *s
ns.Expression = s.Expression.Copy().(Expression)
return ns
}
// ReturnStatement defines an Expression to return
type ReturnStatement struct {
*BaseNode
Argument Expression `json:"argument"`
}
// Type is the abstract type
func (*ReturnStatement) Type() string { return "ReturnStatement" }
func (s *ReturnStatement) Copy() Node {
if s == nil {
return s
}
ns := new(ReturnStatement)
*ns = *s
ns.Argument = s.Argument.Copy().(Expression)
return ns
}
// VariableDeclaration declares one or more variables using assignment
type VariableDeclaration struct {
*BaseNode
Declarations []*VariableDeclarator `json:"declarations"`
}
// Type is the abstract type
func (*VariableDeclaration) Type() string { return "VariableDeclaration" }
func (d *VariableDeclaration) Copy() Node {
if d == nil {
return d
}
nd := new(VariableDeclaration)
*nd = *d
if len(d.Declarations) > 0 {
nd.Declarations = make([]*VariableDeclarator, len(d.Declarations))
for i, decl := range d.Declarations {
nd.Declarations[i] = decl.Copy().(*VariableDeclarator)
}
}
return nd
}
// VariableDeclarator represents the declaration of a variable
type VariableDeclarator struct {
*BaseNode
ID *Identifier `json:"id"`
Init Expression `json:"init"`
}
// Type is the abstract type
func (*VariableDeclarator) Type() string { return "VariableDeclarator" }
func (d *VariableDeclarator) Copy() Node {
if d == nil {
return d
}
nd := new(VariableDeclarator)
*nd = *d
nd.Init = d.Init.Copy().(Expression)
return nd
}
// Expression represents an action that can be performed by InfluxDB that can be evaluated to a value.
type Expression interface {
Node
expression()
}
func (*ArrayExpression) expression() {}
func (*ArrowFunctionExpression) expression() {}
func (*BinaryExpression) expression() {}
func (*BooleanLiteral) expression() {}
func (*CallExpression) expression() {}
func (*ConditionalExpression) expression() {}
func (*DateTimeLiteral) expression() {}
func (*DurationLiteral) expression() {}
func (*FloatLiteral) expression() {}
func (*Identifier) expression() {}
func (*IntegerLiteral) expression() {}
func (*LogicalExpression) expression() {}
func (*MemberExpression) expression() {}
func (*ObjectExpression) expression() {}
func (*PipeExpression) expression() {}
func (*PipeLiteral) expression() {}
func (*RegexpLiteral) expression() {}
func (*StringLiteral) expression() {}
func (*UnaryExpression) expression() {}
func (*UnsignedIntegerLiteral) expression() {}
// CallExpression represents a function all whose callee may be an Identifier or MemberExpression
type CallExpression struct {
*BaseNode
Callee Expression `json:"callee"`
Arguments []Expression `json:"arguments,omitempty"`
}
// Type is the abstract type
func (*CallExpression) Type() string { return "CallExpression" }
func (e *CallExpression) Copy() Node {
if e == nil {
return e
}
ne := new(CallExpression)
*ne = *e
ne.Callee = e.Callee.Copy().(Expression)
if len(e.Arguments) > 0 {
ne.Arguments = make([]Expression, len(e.Arguments))
for i, arg := range e.Arguments {
ne.Arguments[i] = arg.Copy().(Expression)
}
}
return ne
}
type PipeExpression struct {
*BaseNode
Argument Expression `json:"argument"`
Call *CallExpression `json:"call"`
}
// Type is the abstract type
func (*PipeExpression) Type() string { return "PipeExpression" }
func (e *PipeExpression) Copy() Node {
if e == nil {
return e
}
ne := new(PipeExpression)
*ne = *e
ne.Argument = e.Argument.Copy().(Expression)
ne.Call = e.Call.Copy().(*CallExpression)
return ne
}
// MemberExpression represents calling a property of a CallExpression
type MemberExpression struct {
*BaseNode
Object Expression `json:"object"`
Property Expression `json:"property"`
}
// Type is the abstract type
func (*MemberExpression) Type() string { return "MemberExpression" }
func (e *MemberExpression) Copy() Node {
if e == nil {
return e
}
ne := new(MemberExpression)
*ne = *e
ne.Object = e.Object.Copy().(Expression)
ne.Property = e.Property.Copy().(Expression)
return ne
}
type ArrowFunctionExpression struct {
*BaseNode
Params []*Property `json:"params"`
Body Node `json:"body"`
}
// Type is the abstract type
func (*ArrowFunctionExpression) Type() string { return "ArrowFunctionExpression" }
func (e *ArrowFunctionExpression) Copy() Node {
if e == nil {
return e
}
ne := new(ArrowFunctionExpression)
*ne = *e
if len(e.Params) > 0 {
ne.Params = make([]*Property, len(e.Params))
for i, param := range e.Params {
ne.Params[i] = param.Copy().(*Property)
}
}
ne.Body = e.Body.Copy()
return ne
}
// OperatorKind are Equality and Arithmatic operators.
// Result of evaluating an equality operator is always of type Boolean based on whether the
// comparison is true
// Arithmetic operators take numerical values (either literals or variables) as their operands
// and return a single numerical value.
type OperatorKind int
const (
opBegin OperatorKind = iota
MultiplicationOperator
DivisionOperator
AdditionOperator
SubtractionOperator
LessThanEqualOperator
LessThanOperator
GreaterThanEqualOperator
GreaterThanOperator
StartsWithOperator
InOperator
NotOperator
NotEmptyOperator
EmptyOperator
EqualOperator
NotEqualOperator
RegexpMatchOperator
NotRegexpMatchOperator
opEnd
)
func (o OperatorKind) String() string {
return OperatorTokens[o]
}
// OperatorLookup converts the operators to OperatorKind
func OperatorLookup(op string) OperatorKind {
return operators[op]
}
func (o OperatorKind) MarshalText() ([]byte, error) {
text, ok := OperatorTokens[o]
if !ok {
return nil, fmt.Errorf("unknown operator %d", int(o))
}
return []byte(text), nil
}
func (o *OperatorKind) UnmarshalText(data []byte) error {
var ok bool
*o, ok = operators[string(data)]
if !ok {
return fmt.Errorf("unknown operator %q", string(data))
}
return nil
}
// BinaryExpression use binary operators act on two operands in an expression.
// BinaryExpression includes relational and arithmatic operators
type BinaryExpression struct {
*BaseNode
Operator OperatorKind `json:"operator"`
Left Expression `json:"left"`
Right Expression `json:"right"`
}
// Type is the abstract type
func (*BinaryExpression) Type() string { return "BinaryExpression" }
func (e *BinaryExpression) Copy() Node {
if e == nil {
return e
}
ne := new(BinaryExpression)
*ne = *e
ne.Left = e.Left.Copy().(Expression)
ne.Right = e.Right.Copy().(Expression)
return ne
}
// UnaryExpression use operators act on a single operand in an expression.
type UnaryExpression struct {
*BaseNode
Operator OperatorKind `json:"operator"`
Argument Expression `json:"argument"`
}
// Type is the abstract type
func (*UnaryExpression) Type() string { return "UnaryExpression" }
func (e *UnaryExpression) Copy() Node {
if e == nil {
return e
}
ne := new(UnaryExpression)
*ne = *e
ne.Argument = e.Argument.Copy().(Expression)
return ne
}
// LogicalOperatorKind are used with boolean (logical) values
type LogicalOperatorKind int
const (
logOpBegin LogicalOperatorKind = iota
AndOperator
OrOperator
logOpEnd
)
func (o LogicalOperatorKind) String() string {
return LogicalOperatorTokens[o]
}
// LogicalOperatorLookup converts the operators to LogicalOperatorKind
func LogicalOperatorLookup(op string) LogicalOperatorKind {
return logOperators[op]
}
func (o LogicalOperatorKind) MarshalText() ([]byte, error) {
text, ok := LogicalOperatorTokens[o]
if !ok {
return nil, fmt.Errorf("unknown logical operator %d", int(o))
}
return []byte(text), nil
}
func (o *LogicalOperatorKind) UnmarshalText(data []byte) error {
var ok bool
*o, ok = logOperators[string(data)]
if !ok {
return fmt.Errorf("unknown logical operator %q", string(data))
}
return nil
}
// LogicalExpression represent the rule conditions that collectively evaluate to either true or false.
// `or` expressions compute the disjunction of two boolean expressions and return boolean values.
// `and`` expressions compute the conjunction of two boolean expressions and return boolean values.
type LogicalExpression struct {
*BaseNode
Operator LogicalOperatorKind `json:"operator"`
Left Expression `json:"left"`
Right Expression `json:"right"`
}
// Type is the abstract type
func (*LogicalExpression) Type() string { return "LogicalExpression" }
func (e *LogicalExpression) Copy() Node {
if e == nil {
return e
}
ne := new(LogicalExpression)
*ne = *e
ne.Left = e.Left.Copy().(Expression)
ne.Right = e.Right.Copy().(Expression)
return ne
}
// ArrayExpression is used to create and directly specify the elements of an array object
type ArrayExpression struct {
*BaseNode
Elements []Expression `json:"elements"`
}
// Type is the abstract type
func (*ArrayExpression) Type() string { return "ArrayExpression" }
func (e *ArrayExpression) Copy() Node {
if e == nil {
return e
}
ne := new(ArrayExpression)
*ne = *e
if len(e.Elements) > 0 {
ne.Elements = make([]Expression, len(e.Elements))
for i, el := range e.Elements {
ne.Elements[i] = el.Copy().(Expression)
}
}
return ne
}
// ObjectExpression allows the declaration of an anonymous object within a declaration.
type ObjectExpression struct {
*BaseNode
Properties []*Property `json:"properties"`
}
// Type is the abstract type
func (*ObjectExpression) Type() string { return "ObjectExpression" }
func (e *ObjectExpression) Copy() Node {
if e == nil {
return e
}
ne := new(ObjectExpression)
*ne = *e
if len(e.Properties) > 0 {
ne.Properties = make([]*Property, len(e.Properties))
for i, p := range e.Properties {
ne.Properties[i] = p.Copy().(*Property)
}
}
return ne
}
// ConditionalExpression selects one of two expressions, `Alternate` or `Consequent`
// depending on a third, boolean, expression, `Test`.
type ConditionalExpression struct {
*BaseNode
Test Expression `json:"test"`
Alternate Expression `json:"alternate"`
Consequent Expression `json:"consequent"`
}
// Type is the abstract type
func (*ConditionalExpression) Type() string { return "ConditionalExpression" }
func (e *ConditionalExpression) Copy() Node {
if e == nil {
return e
}
ne := new(ConditionalExpression)
*ne = *e
ne.Test = e.Test.Copy().(Expression)
ne.Alternate = e.Alternate.Copy().(Expression)
ne.Consequent = e.Consequent.Copy().(Expression)
return ne
}
// Property is the value associated with a key
type Property struct {
*BaseNode
Key *Identifier `json:"key"`
Value Expression `json:"value"`
}
func (p *Property) Copy() Node {
if p == nil {
return p
}
np := new(Property)
*np = *p
if p.Value != nil {
np.Value = p.Value.Copy().(Expression)
}
return np
}
// Type is the abstract type
func (*Property) Type() string { return "Property" }
// Identifier represents a name that identifies a unique Node
type Identifier struct {
*BaseNode
Name string `json:"name"`
}
// Type is the abstract type
func (*Identifier) Type() string { return "Identifier" }
func (i *Identifier) Copy() Node {
if i == nil {
return i
}
ni := new(Identifier)
*ni = *i
return ni
}
// Literal are thelexical forms for literal expressions which define
// boolean, string, integer, number, duration, datetime and field values.
// Literals must be coerced explicitly.
type Literal interface {
Expression
literal()
}
func (*BooleanLiteral) literal() {}
func (*DateTimeLiteral) literal() {}
func (*DurationLiteral) literal() {}
func (*FloatLiteral) literal() {}
func (*IntegerLiteral) literal() {}
func (*PipeLiteral) literal() {}
func (*RegexpLiteral) literal() {}
func (*StringLiteral) literal() {}
func (*UnsignedIntegerLiteral) literal() {}
// PipeLiteral represents an specialized literal value, indicating the left hand value of a pipe expression.
type PipeLiteral struct {
*BaseNode
}
// Type is the abstract type
func (*PipeLiteral) Type() string { return "PipeLiteral" }
func (i *PipeLiteral) Copy() Node {
if i == nil {
return i
}
ni := new(PipeLiteral)
*ni = *i
return ni
}
// StringLiteral expressions begin and end with double quote marks.
type StringLiteral struct {
*BaseNode
Value string `json:"value"`
}
func (*StringLiteral) Type() string { return "StringLiteral" }
func (l *StringLiteral) Copy() Node {
if l == nil {
return l
}
nl := new(StringLiteral)
*nl = *l
return nl
}
// BooleanLiteral represent boolean values
type BooleanLiteral struct {
*BaseNode
Value bool `json:"value"`
}
// Type is the abstract type
func (*BooleanLiteral) Type() string { return "BooleanLiteral" }
func (l *BooleanLiteral) Copy() Node {
if l == nil {
return l
}
nl := new(BooleanLiteral)
*nl = *l
return nl
}
// FloatLiteral represent floating point numbers according to the double representations defined by the IEEE-754-1985
type FloatLiteral struct {
*BaseNode
Value float64 `json:"value"`
}
// Type is the abstract type
func (*FloatLiteral) Type() string { return "FloatLiteral" }
func (l *FloatLiteral) Copy() Node {
if l == nil {
return l
}
nl := new(FloatLiteral)
*nl = *l
return nl
}
// IntegerLiteral represent integer numbers.
type IntegerLiteral struct {
*BaseNode
Value int64 `json:"value"`
}
// Type is the abstract type
func (*IntegerLiteral) Type() string { return "IntegerLiteral" }
func (l *IntegerLiteral) Copy() Node {
if l == nil {
return l
}
nl := new(IntegerLiteral)
*nl = *l
return nl
}
// UnsignedIntegerLiteral represent integer numbers.
type UnsignedIntegerLiteral struct {
*BaseNode
Value uint64 `json:"value"`
}
// Type is the abstract type
func (*UnsignedIntegerLiteral) Type() string { return "UnsignedIntegerLiteral" }
func (l *UnsignedIntegerLiteral) Copy() Node {
if l == nil {
return l
}
nl := new(UnsignedIntegerLiteral)
*nl = *l
return nl
}
// RegexpLiteral expressions begin and end with `/` and are regular expressions with syntax accepted by RE2
type RegexpLiteral struct {
*BaseNode
Value *regexp.Regexp `json:"value"`
}
// Type is the abstract type
func (*RegexpLiteral) Type() string { return "RegexpLiteral" }
func (l *RegexpLiteral) Copy() Node {
if l == nil {
return l
}
nl := new(RegexpLiteral)
*nl = *l
return nl
}
// DurationLiteral represents the elapsed time between two instants as an
// int64 nanosecond count with syntax of golang's time.Duration
// TODO: this may be better as a class initialization
type DurationLiteral struct {
*BaseNode
Value time.Duration `json:"value"`
}
// Type is the abstract type
func (*DurationLiteral) Type() string { return "DurationLiteral" }
func (l *DurationLiteral) Copy() Node {
if l == nil {
return l
}
nl := new(DurationLiteral)
*nl = *l
return nl
}
// DateTimeLiteral represents an instant in time with nanosecond precision using
// the syntax of golang's RFC3339 Nanosecond variant
// TODO: this may be better as a class initialization
type DateTimeLiteral struct {
*BaseNode
Value time.Time `json:"value"`
}
// Type is the abstract type
func (*DateTimeLiteral) Type() string { return "DateTimeLiteral" }
func (l *DateTimeLiteral) Copy() Node {
if l == nil {
return l
}
nl := new(DateTimeLiteral)
*nl = *l
return nl
}
// OperatorTokens converts OperatorKind to string
var OperatorTokens = map[OperatorKind]string{
MultiplicationOperator: "*",
DivisionOperator: "/",
AdditionOperator: "+",
SubtractionOperator: "-",
LessThanEqualOperator: "<=",
LessThanOperator: "<",
GreaterThanOperator: ">",
GreaterThanEqualOperator: ">=",
InOperator: "in",
NotOperator: "not",
NotEmptyOperator: "not empty",
EmptyOperator: "empty",
StartsWithOperator: "startswith",
EqualOperator: "==",
NotEqualOperator: "!=",
RegexpMatchOperator: "=~",
NotRegexpMatchOperator: "!~",
}
// LogicalOperatorTokens converts LogicalOperatorKind to string
var LogicalOperatorTokens = map[LogicalOperatorKind]string{
AndOperator: "and",
OrOperator: "or",
}
var operators map[string]OperatorKind
var logOperators map[string]LogicalOperatorKind
func init() {
operators = make(map[string]OperatorKind)
for op := opBegin + 1; op < opEnd; op++ {
operators[OperatorTokens[op]] = op
}
logOperators = make(map[string]LogicalOperatorKind)
for op := logOpBegin + 1; op < logOpEnd; op++ {
logOperators[LogicalOperatorTokens[op]] = op
}
}