feat(http): define external preprocessing options via http api (#11939)

Closes #11702.
pull/11916/head
jlapacik 2019-02-21 13:11:50 -08:00 committed by GitHub
parent 817e45d60d
commit af258e62e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 683 additions and 134 deletions

2
go.mod
View File

@ -62,7 +62,7 @@ require (
github.com/hashicorp/vault v0.11.5
github.com/hashicorp/vault-plugin-secrets-kv v0.0.0-20181106190520-2236f141171e // indirect
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect
github.com/influxdata/flux v0.20.0
github.com/influxdata/flux v0.20.1-0.20190220204516-5138168746ee
github.com/influxdata/influxql v0.0.0-20180925231337-1cbfca8e56b6
github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368
github.com/jefferai/jsonx v0.0.0-20160721235117-9cc31c3135ee // indirect

4
go.sum
View File

@ -224,8 +224,8 @@ github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/flux v0.20.0 h1:v+R/pQGamzx5XVB03dCuVnHPnoreLTNLDrrNJkS5xEA=
github.com/influxdata/flux v0.20.0/go.mod h1:0f5Yrm4VPSd/Ne6jIVOVtPo0MFe6jpLCr6vdaZYp7wY=
github.com/influxdata/flux v0.20.1-0.20190220204516-5138168746ee h1:Mlg8OS1IHpAHOHlrsb0oi/Rn6yVkI68IrqCbkWbXWBQ=
github.com/influxdata/flux v0.20.1-0.20190220204516-5138168746ee/go.mod h1:0f5Yrm4VPSd/Ne6jIVOVtPo0MFe6jpLCr6vdaZYp7wY=
github.com/influxdata/goreleaser v0.97.0-influx/go.mod h1:MnjA0e0Uq6ISqjG1WxxMAl+3VS1QYjILSWVnMYDxasE=
github.com/influxdata/influxql v0.0.0-20180925231337-1cbfca8e56b6 h1:CFx+pP90q/qg3spoiZjf8donE4WpAdjeJfPOcoNqkWo=
github.com/influxdata/influxql v0.0.0-20180925231337-1cbfca8e56b6/go.mod h1:KpVI7okXjK6PRi3Z5B+mtKZli+R1DnZgb3N+tzevNgo=

View File

@ -16,25 +16,23 @@ import (
"github.com/influxdata/flux"
"github.com/influxdata/flux/ast"
"github.com/influxdata/flux/csv"
"github.com/influxdata/flux/interpreter"
"github.com/influxdata/flux/lang"
"github.com/influxdata/flux/parser"
"github.com/influxdata/flux/semantic"
"github.com/influxdata/flux/values"
platform "github.com/influxdata/influxdb"
"github.com/influxdata/influxdb"
"github.com/influxdata/influxdb/query"
"github.com/influxdata/influxql"
)
// QueryRequest is a flux query request.
type QueryRequest struct {
Extern *ast.File `json:"extern,omitempty"`
Spec *flux.Spec `json:"spec,omitempty"`
AST *ast.Package `json:"ast,omitempty"`
Query string `json:"query"`
Type string `json:"type"`
Dialect QueryDialect `json:"dialect"`
Org *platform.Organization `json:"-"`
Org *influxdb.Organization `json:"-"`
}
// QueryDialect is the formatting options for the query response.
@ -70,6 +68,13 @@ func (r QueryRequest) Validate() error {
return errors.New(`request body requires either query, spec, or AST`)
}
if r.Spec != nil && r.Extern != nil {
return &influxdb.Error{
Code: influxdb.EInvalid,
Msg: "request body cannot specify both a spec and external declarations",
}
}
if r.Type != "flux" {
return fmt.Errorf(`unknown query type: %s`, r.Type)
}
@ -206,47 +211,6 @@ func columnFromCharacter(q string, char int) int {
var influxqlParseErrorRE = regexp.MustCompile(`^(.+) at line (\d+), char (\d+)$`)
func nowFunc(now time.Time) values.Function {
timeVal := values.NewTime(values.ConvertTime(now))
ftype := semantic.NewFunctionPolyType(semantic.FunctionPolySignature{
Return: semantic.Time,
})
call := func(args values.Object) (values.Value, error) {
return timeVal, nil
}
sideEffect := false
return values.NewFunction("now", ftype, call, sideEffect)
}
func toSpec(p *ast.Package, now func() time.Time) (*flux.Spec, error) {
semProg, err := semantic.New(p)
if err != nil {
return nil, err
}
scope := flux.Prelude()
scope.Set("now", nowFunc(now()))
itrp := interpreter.NewInterpreter()
sideEffects, err := itrp.Eval(semProg, scope, flux.StdLib())
if err != nil {
return nil, err
}
nowOpt, ok := scope.Lookup("now")
if !ok {
return nil, fmt.Errorf("now option not set")
}
nowTime, err := nowOpt.Function().Call(nil)
if err != nil {
return nil, err
}
return flux.ToSpec(sideEffects, nowTime.Time().Time())
}
// ProxyRequest returns a request to proxy from the flux.
func (r QueryRequest) ProxyRequest() (*query.ProxyRequest, error) {
return r.proxyRequest(time.Now)
@ -259,18 +223,27 @@ func (r QueryRequest) proxyRequest(now func() time.Time) (*query.ProxyRequest, e
// Query is preferred over spec
var compiler flux.Compiler
if r.Query != "" {
compiler = lang.FluxCompiler{
Query: r.Query,
}
} else if r.AST != nil {
var err error
r.Spec, err = toSpec(r.AST, now)
pkg, err := flux.Parse(r.Query)
if err != nil {
return nil, err
}
compiler = lang.SpecCompiler{
Spec: r.Spec,
c := lang.ASTCompiler{
AST: pkg,
Now: now,
}
if r.Extern != nil {
c.PrependFile(r.Extern)
}
compiler = c
} else if r.AST != nil {
c := lang.ASTCompiler{
AST: r.AST,
Now: now,
}
if r.Extern != nil {
c.PrependFile(r.Extern)
}
compiler = c
} else if r.Spec != nil {
compiler = lang.SpecCompiler{
Spec: r.Spec,
@ -312,6 +285,9 @@ func QueryRequestFromProxyRequest(req *query.ProxyRequest) (*QueryRequest, error
case lang.SpecCompiler:
qr.Type = "flux"
qr.Spec = c.Spec
case lang.ASTCompiler:
qr.Type = "flux"
qr.AST = c.AST
default:
return nil, fmt.Errorf("unsupported compiler %T", c)
}
@ -330,7 +306,7 @@ func QueryRequestFromProxyRequest(req *query.ProxyRequest) (*QueryRequest, error
return qr, nil
}
func decodeQueryRequest(ctx context.Context, r *http.Request, svc platform.OrganizationService) (*QueryRequest, error) {
func decodeQueryRequest(ctx context.Context, r *http.Request, svc influxdb.OrganizationService) (*QueryRequest, error) {
var req QueryRequest
var contentType = "application/json"
@ -365,7 +341,7 @@ func decodeQueryRequest(ctx context.Context, r *http.Request, svc platform.Organ
return &req, err
}
func decodeProxyQueryRequest(ctx context.Context, r *http.Request, auth platform.Authorizer, svc platform.OrganizationService) (*query.ProxyRequest, error) {
func decodeProxyQueryRequest(ctx context.Context, r *http.Request, auth influxdb.Authorizer, svc influxdb.OrganizationService) (*query.ProxyRequest, error) {
req, err := decodeQueryRequest(ctx, r, svc)
if err != nil {
return nil, err
@ -376,10 +352,10 @@ func decodeProxyQueryRequest(ctx context.Context, r *http.Request, auth platform
return nil, err
}
a, ok := auth.(*platform.Authorization)
a, ok := auth.(*influxdb.Authorization)
if !ok {
// TODO(desa): this should go away once we're using platform.Authorizers everywhere.
return pr, platform.ErrAuthorizerNotSupported
// TODO(desa): this should go away once we're using influxdb.Authorizers everywhere.
return pr, influxdb.ErrAuthorizerNotSupported
}
pr.Request.Authorization = a

View File

@ -22,6 +22,27 @@ import (
_ "github.com/influxdata/influxdb/query/builtin"
)
var compareASTCompiler = func(x, y lang.ASTCompiler) bool {
if x.Now == nil && y.Now != nil {
return false
}
if x.Now != nil && y.Now == nil {
return false
}
if x.Now != nil && y.Now != nil && !x.Now().Equal(y.Now()) {
return false
}
return cmp.Equal(x.AST, y.AST, cmpopts.IgnoreTypes(ast.BaseNode{}))
}
var cmpOptions = cmp.Options{
cmpopts.IgnoreTypes(ast.BaseNode{}),
cmpopts.IgnoreUnexported(query.ProxyRequest{}),
cmpopts.IgnoreUnexported(query.Request{}),
cmpopts.IgnoreUnexported(flux.Spec{}),
cmpopts.EquateEmpty(),
}
func TestQueryRequest_WithDefaults(t *testing.T) {
type fields struct {
Spec *flux.Spec
@ -67,6 +88,7 @@ func TestQueryRequest_WithDefaults(t *testing.T) {
func TestQueryRequest_Validate(t *testing.T) {
type fields struct {
Extern *ast.File
Spec *flux.Spec
AST *ast.Package
Query string
@ -86,6 +108,19 @@ func TestQueryRequest_Validate(t *testing.T) {
},
wantErr: true,
},
{
name: "query cannot have both extern and spec",
fields: fields{
Extern: &ast.File{},
Spec: &flux.Spec{},
Type: "flux",
Dialect: QueryDialect{
Delimiter: ",",
DateTimeFormat: "RFC3339",
},
},
wantErr: true,
},
{
name: "requires flux type",
fields: fields{
@ -166,6 +201,7 @@ func TestQueryRequest_Validate(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := QueryRequest{
Extern: tt.fields.Extern,
Spec: tt.fields.Spec,
AST: tt.fields.AST,
Query: tt.fields.Query,
@ -180,59 +216,9 @@ func TestQueryRequest_Validate(t *testing.T) {
}
}
func Test_toSpec(t *testing.T) {
type args struct {
p *ast.Package
now func() time.Time
}
tests := []struct {
name string
args args
want *flux.Spec
wantErr bool
}{
{
name: "ast converts to spec",
args: args{
p: &ast.Package{},
now: func() time.Time { return time.Unix(0, 0) },
},
want: &flux.Spec{
Now: time.Unix(0, 0).UTC(),
},
},
{
name: "bad semantics error",
args: args{
p: &ast.Package{
Files: []*ast.File{{
Body: []ast.Statement{
&ast.ReturnStatement{},
},
}},
},
now: func() time.Time { return time.Unix(0, 0) },
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := toSpec(tt.args.p, tt.args.now)
if (err != nil) != tt.wantErr {
t.Errorf("toSpec() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("toSpec() = %v, want %v", got, tt.want)
}
})
}
}
func TestQueryRequest_proxyRequest(t *testing.T) {
type fields struct {
Extern *ast.File
Spec *flux.Spec
AST *ast.Package
Query string
@ -265,10 +251,23 @@ func TestQueryRequest_proxyRequest(t *testing.T) {
},
org: &platform.Organization{},
},
now: func() time.Time { return time.Unix(1, 1) },
want: &query.ProxyRequest{
Request: query.Request{
Compiler: lang.FluxCompiler{
Query: "howdy",
Compiler: lang.ASTCompiler{
AST: &ast.Package{
Package: "main",
Files: []*ast.File{
{
Body: []ast.Statement{
&ast.ExpressionStatement{
Expression: &ast.Identifier{Name: "howdy"},
},
},
},
},
},
Now: func() time.Time { return time.Unix(1, 1) },
},
},
Dialect: &csv.Dialect{
@ -290,15 +289,64 @@ func TestQueryRequest_proxyRequest(t *testing.T) {
},
org: &platform.Organization{},
},
now: func() time.Time { return time.Unix(0, 0).UTC() },
now: func() time.Time { return time.Unix(1, 1) },
want: &query.ProxyRequest{
Request: query.Request{
Compiler: lang.SpecCompiler{
Spec: &flux.Spec{
Now: time.Unix(0, 0).UTC(),
Compiler: lang.ASTCompiler{
AST: &ast.Package{},
Now: func() time.Time { return time.Unix(1, 1) },
},
},
Dialect: &csv.Dialect{
ResultEncoderConfig: csv.ResultEncoderConfig{
NoHeader: false,
Delimiter: ',',
},
},
},
},
{
name: "valid AST with extern",
fields: fields{
Extern: &ast.File{
Body: []ast.Statement{
&ast.OptionStatement{
Assignment: &ast.VariableAssignment{
ID: &ast.Identifier{Name: "x"},
Init: &ast.IntegerLiteral{Value: 0},
},
},
},
},
AST: &ast.Package{},
Type: "flux",
Dialect: QueryDialect{
Delimiter: ",",
DateTimeFormat: "RFC3339",
},
org: &platform.Organization{},
},
now: func() time.Time { return time.Unix(1, 1) },
want: &query.ProxyRequest{
Request: query.Request{
Compiler: lang.ASTCompiler{
AST: &ast.Package{
Files: []*ast.File{
{
Body: []ast.Statement{
&ast.OptionStatement{
Assignment: &ast.VariableAssignment{
ID: &ast.Identifier{Name: "x"},
Init: &ast.IntegerLiteral{Value: 0},
},
},
},
},
},
},
Now: func() time.Time { return time.Unix(1, 1) },
},
},
Dialect: &csv.Dialect{
ResultEncoderConfig: csv.ResultEncoderConfig{
NoHeader: false,
@ -337,9 +385,11 @@ func TestQueryRequest_proxyRequest(t *testing.T) {
},
},
}
cmpOptions := append(cmpOptions, cmp.Comparer(compareASTCompiler))
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := QueryRequest{
Extern: tt.fields.Extern,
Spec: tt.fields.Spec,
AST: tt.fields.AST,
Query: tt.fields.Query,
@ -352,8 +402,8 @@ func TestQueryRequest_proxyRequest(t *testing.T) {
t.Errorf("QueryRequest.ProxyRequest() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("QueryRequest.ProxyRequest() = %#v, want %#v", got, tt.want)
if !cmp.Equal(got, tt.want, cmpOptions...) {
t.Errorf("QueryRequest.ProxyRequest() -want/+got\n%s", cmp.Diff(tt.want, got, cmpOptions...))
}
})
}
@ -482,8 +532,104 @@ func Test_decodeProxyQueryRequest(t *testing.T) {
want: &query.ProxyRequest{
Request: query.Request{
OrganizationID: func() platform.ID { s, _ := platform.IDFromString("deadbeefdeadbeef"); return *s }(),
Compiler: lang.FluxCompiler{
Query: "from()",
Compiler: lang.ASTCompiler{
AST: &ast.Package{
Package: "main",
Files: []*ast.File{
{
Body: []ast.Statement{
&ast.ExpressionStatement{
Expression: &ast.CallExpression{
Callee: &ast.Identifier{Name: "from"},
},
},
},
},
},
},
},
},
Dialect: &csv.Dialect{
ResultEncoderConfig: csv.ResultEncoderConfig{
NoHeader: false,
Delimiter: ',',
},
},
},
},
{
name: "valid query including extern definition",
args: args{
r: httptest.NewRequest("POST", "/", bytes.NewBufferString(`
{
"extern": {
"type": "File",
"body": [
{
"type": "OptionStatement",
"assignment": {
"type": "VariableAssignment",
"id": {
"type": "Identifier",
"name": "x"
},
"init": {
"type": "IntegerLiteral",
"value": "0"
}
}
}
]
},
"query": "from(bucket: \"mybucket\")"
}
`)),
svc: &mock.OrganizationService{
FindOrganizationF: func(ctx context.Context, filter platform.OrganizationFilter) (*platform.Organization, error) {
return &platform.Organization{
ID: func() platform.ID { s, _ := platform.IDFromString("deadbeefdeadbeef"); return *s }(),
}, nil
},
},
},
want: &query.ProxyRequest{
Request: query.Request{
OrganizationID: func() platform.ID { s, _ := platform.IDFromString("deadbeefdeadbeef"); return *s }(),
Compiler: lang.ASTCompiler{
AST: &ast.Package{
Package: "main",
Files: []*ast.File{
{
Body: []ast.Statement{
&ast.OptionStatement{
Assignment: &ast.VariableAssignment{
ID: &ast.Identifier{Name: "x"},
Init: &ast.IntegerLiteral{Value: 0},
},
},
},
},
{
Body: []ast.Statement{
&ast.ExpressionStatement{
Expression: &ast.CallExpression{
Callee: &ast.Identifier{Name: "from"},
Arguments: []ast.Expression{
&ast.ObjectExpression{
Properties: []*ast.Property{
{
Key: &ast.Identifier{Name: "bucket"},
Value: &ast.StringLiteral{Value: "mybucket"},
},
},
},
},
},
},
},
},
},
},
},
},
Dialect: &csv.Dialect{
@ -513,8 +659,31 @@ func Test_decodeProxyQueryRequest(t *testing.T) {
want: &query.ProxyRequest{
Request: query.Request{
OrganizationID: func() platform.ID { s, _ := platform.IDFromString("deadbeefdeadbeef"); return *s }(),
Compiler: lang.FluxCompiler{
Query: "from(bucket: \"mybucket\")",
Compiler: lang.ASTCompiler{
AST: &ast.Package{
Package: "main",
Files: []*ast.File{
{
Body: []ast.Statement{
&ast.ExpressionStatement{
Expression: &ast.CallExpression{
Callee: &ast.Identifier{Name: "from"},
Arguments: []ast.Expression{
&ast.ObjectExpression{
Properties: []*ast.Property{
{
Key: &ast.Identifier{Name: "bucket"},
Value: &ast.StringLiteral{Value: "mybucket"},
},
},
},
},
},
},
},
},
},
},
},
},
Dialect: &csv.Dialect{
@ -526,11 +695,7 @@ func Test_decodeProxyQueryRequest(t *testing.T) {
},
},
}
var cmpOptions = cmp.Options{
cmpopts.IgnoreUnexported(query.ProxyRequest{}),
cmpopts.IgnoreUnexported(query.Request{}),
cmpopts.EquateEmpty(),
}
cmpOptions := append(cmpOptions, cmpopts.IgnoreFields(lang.ASTCompiler{}, "Now"))
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := decodeProxyQueryRequest(tt.args.ctx, tt.args.r, tt.args.auth, tt.args.svc)
@ -538,8 +703,8 @@ func Test_decodeProxyQueryRequest(t *testing.T) {
t.Errorf("decodeProxyQueryRequest() error = %v, wantErr %v", err, tt.wantErr)
return
}
if diff := cmp.Diff(got, tt.want, cmpOptions...); diff != "" {
t.Errorf("decodeProxyQueryRequest() = got/want %v", diff)
if !cmp.Equal(tt.want, got, cmpOptions...) {
t.Errorf("decodeProxyQueryRequest() -want/+got\n%s", cmp.Diff(tt.want, got, cmpOptions...))
}
})
}

View File

@ -4688,6 +4688,8 @@ components:
required:
- query
properties:
extern:
$ref: "#/components/schemas/File"
query:
description: query script to execute.
type: string
@ -4711,6 +4713,413 @@ components:
type: string
dialect:
$ref: "#/components/schemas/Dialect"
Package:
description: represents a complete package source tree
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
path:
description: package import path
type: string
package:
description: package name
type: string
files:
description: package files
type: array
items:
$ref: "#/components/schemas/File"
File:
description: represents a source from a single file
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
name:
description: name of the file
type: string
package:
$ref: "#/components/schemas/PackageClause"
imports:
description: a list of package imports
type: array
items:
$ref: "#/components/schemas/ImportDeclaration"
body:
description: list of Flux statements
type: array
items:
$ref: "#/components/schemas/Statement"
PackageClause:
description: defines a package identifier
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
name:
$ref: "#/components/schemas/Identifier"
ImportDeclaration:
description: declares a package import
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
as:
$ref: "#/components/schemas/Identifier"
path:
$ref: "#/components/schemas/StringLiteral"
Node:
oneOf:
- $ref: "#/components/schemas/Expression"
- $ref: "#/components/schemas/Block"
Block:
description: a set of statements
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
body:
description: block body
type: array
items:
$ref: "#/components/schemas/Statement"
Statement:
oneOf:
- $ref: "#/components/schemas/BadStatement"
- $ref: "#/components/schemas/VariableAssignment"
- $ref: "#/components/schemas/MemberAssignment"
- $ref: "#/components/schemas/ExpressionStatement"
- $ref: "#/components/schemas/ReturnStatement"
- $ref: "#/components/schemas/OptionStatement"
- $ref: "#/components/schemas/BuiltinStatement"
- $ref: "#/components/schemas/TestStatement"
BadStatement:
description: a placeholder for statements for which no correct statement nodes can be created
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
text:
description: raw source text
type: string
VariableAssignment:
description: represents the declaration of a variable
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
id:
$ref: "#/components/schemas/Identifier"
init:
$ref: "#/components/schemas/Expression"
MemberAssignment:
description: object property assignment
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
member:
$ref: "#/components/schemas/MemberExpression"
init:
$ref: "#/components/schemas/Expression"
ExpressionStatement:
description: may consist of an expression that does not return a value and is executed solely for its side-effects
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
expression:
$ref: "#/components/schemas/Expression"
ReturnStatement:
description: defines an expression to return
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
argument:
$ref: "#/components/schemas/Expression"
OptionStatement:
description: a single variable declaration
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
assignment:
oneOf:
- $ref: "#/components/schemas/VariableAssignment"
- $ref: "#/components/schemas/MemberAssignment"
BuiltinStatement:
description: declares a builtin identifier and its type
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
id:
$ref: "#/components/schemas/Identifier"
TestStatement:
description: declares a Flux test case
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
assignment:
$ref: "#/components/schemas/VariableAssignment"
Expression:
oneOf:
- $ref: "#/components/schemas/ArrayExpression"
- $ref: "#/components/schemas/FunctionExpression"
- $ref: "#/components/schemas/BinaryExpression"
- $ref: "#/components/schemas/CallExpression"
- $ref: "#/components/schemas/ConditionalExpression"
- $ref: "#/components/schemas/LogicalExpression"
- $ref: "#/components/schemas/MemberExpression"
- $ref: "#/components/schemas/IndexExpression"
- $ref: "#/components/schemas/ObjectExpression"
- $ref: "#/components/schemas/PipeExpression"
- $ref: "#/components/schemas/UnaryExpression"
- $ref: "#/components/schemas/BooleanLiteral"
- $ref: "#/components/schemas/DateTimeLiteral"
- $ref: "#/components/schemas/DurationLiteral"
- $ref: "#/components/schemas/FloatLiteral"
- $ref: "#/components/schemas/IntegerLiteral"
- $ref: "#/components/schemas/PipeLiteral"
- $ref: "#/components/schemas/RegexpLiteral"
- $ref: "#/components/schemas/StringLiteral"
- $ref: "#/components/schemas/UnsignedIntegerLiteral"
- $ref: "#/components/schemas/Identifier"
ArrayExpression:
description: used to create and directly specify the elements of an array object
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
elements:
description: elements of the array
type: array
items:
$ref: "#/components/schemas/Expression"
FunctionExpression:
description: function expression
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
params:
description: function parameters
type: array
items:
$ref: "#/components/schemas/Property"
body:
$ref: "#/components/schemas/Node"
BinaryExpression:
description: uses binary operators to act on two operands in an expression
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
operator:
type: string
left:
$ref: "#/components/schemas/Expression"
right:
$ref: "#/components/schemas/Expression"
CallExpression:
description: represents a function call
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
callee:
$ref: "#/components/schemas/Expression"
arguments:
description: function arguments
type: array
items:
$ref: "#/components/schemas/Expression"
ConditionalExpression:
description: selects one of two expressions, `Alternate` or `Consequent`, depending on a third boolean expression, `Test`
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
test:
$ref: "#/components/schemas/Expression"
alternate:
$ref: "#/components/schemas/Expression"
consequent:
$ref: "#/components/schemas/Expression"
LogicalExpression:
description: represents the rule conditions that collectively evaluate to either true or false
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
operator:
type: string
left:
$ref: "#/components/schemas/Expression"
right:
$ref: "#/components/schemas/Expression"
MemberExpression:
description: represents accessing a property of an object
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
object:
$ref: "#/components/schemas/Expression"
property:
$ref: "#/components/schemas/PropertyKey"
IndexExpression:
description: represents indexing into an array
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
array:
$ref: "#/components/schemas/Expression"
index:
$ref: "#/components/schemas/Expression"
ObjectExpression:
description: allows the declaration of an anonymous object within a declaration
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
properties:
description: object properties
type: array
items:
$ref: "#/components/schemas/Property"
PipeExpression:
description: call expression with pipe argument
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
argument:
$ref: "#/components/schemas/Expression"
call:
$ref: "#/components/schemas/CallExpression"
UnaryExpression:
description: uses operators to act on a single operand in an expression
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
operator:
type: string
argument:
$ref: "#/components/schemas/Expression"
BooleanLiteral:
description: represents boolean values
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
value:
type: boolean
DateTimeLiteral:
description: represents an instant in time with nanosecond precision using the syntax of golang's RFC3339 Nanosecond variant
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
value:
type: string
DurationLiteral:
description: represents the elapsed time between two instants as an int64 nanosecond count with syntax of golang's time.Duration
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
values:
description: duration values
type: array
items:
$ref: "#/components/schemas/Duration"
FloatLiteral:
description: represents floating point numbers according to the double representations defined by the IEEE-754-1985
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
value:
type: number
IntegerLiteral:
description: represents integer numbers
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
value:
type: string
PipeLiteral:
description: represents a specialized literal value, indicating the left hand value of a pipe expression
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
RegexpLiteral:
description: expressions begin and end with `/` and are regular expressions with syntax accepted by RE2
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
value:
type: string
StringLiteral:
description: expressions begin and end with double quote marks
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
value:
type: string
UnsignedIntegerLiteral:
description: represents integer numbers
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
value:
type: string
Duration:
description: a pair consisting of length of time and the unit of time measured. It is the atomic unit from which all duration literals are composed.
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
magnitude:
type: integer
unit:
type: string
Property:
description: the value associated with a key
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
key:
$ref: "#/components/schemas/PropertyKey"
value:
$ref: "#/components/schemas/Expression"
PropertyKey:
oneOf:
- $ref: "#/components/schemas/Identifier"
- $ref: "#/components/schemas/StringLiteral"
Identifier:
description: a valid Flux identifier
type: object
properties:
type:
$ref: "#/components/schemas/NodeType"
name:
type: string
NodeType:
description: type of AST node
type: string
QuerySpecification:
description: consists of a set of operations and a set of edges between those operations to instruct the query engine to operate.
type: object
@ -7087,8 +7496,7 @@ components:
type: object
properties:
ast:
description: the AST of the supplied Flux query
type: object
$ref: "#/components/schemas/Package"
WritePrecision:
type: string
enum: