chore(query/builtin): Add package to formalize query builtin initialization

Now all packages wishing to consume query package can and must import
query/builtin in order to properly initialize all builtin values.
pull/10616/head
Nathaniel Cook 2018-05-31 11:47:33 -06:00
parent e18ca56fb5
commit 5e30d7cdd6
11 changed files with 87 additions and 74 deletions

View File

@ -13,6 +13,7 @@ import (
"github.com/influxdata/platform"
"github.com/influxdata/platform/http"
"github.com/influxdata/platform/query"
_ "github.com/influxdata/platform/query/builtin"
"github.com/influxdata/platform/query/control"
"github.com/influxdata/platform/query/execute"
"github.com/influxdata/platform/query/functions"

View File

@ -2,15 +2,13 @@ package main
import (
"fmt"
"math"
"os"
"runtime"
"strings"
"github.com/influxdata/platform"
"github.com/influxdata/platform/http"
"github.com/influxdata/platform/query"
"github.com/influxdata/platform/query/control"
_ "github.com/influxdata/platform/query/builtin"
"github.com/influxdata/platform/query/execute"
"github.com/influxdata/platform/query/functions"
"github.com/influxdata/platform/query/functions/storage"
@ -120,19 +118,3 @@ func orgID(org string) (ifqlid.ID, error) {
err := oid.DecodeFromString(org)
return oid, err
}
func getIFQLREPL(storageHosts storage.Reader, buckets platform.BucketService, org ifqlid.ID, verbose bool) (*repl.REPL, error) {
conf := control.Config{
ExecutorDependencies: make(execute.Dependencies),
ConcurrencyQuota: runtime.NumCPU() * 2,
MemoryBytesQuota: math.MaxInt64,
Verbose: verbose,
}
if err := injectDeps(conf.ExecutorDependencies, storageHosts, buckets); err != nil {
return nil, err
}
c := control.New(conf)
return repl.New(c, org), nil
}

View File

@ -2,9 +2,18 @@ package main
import (
"fmt"
"math"
"os"
"runtime"
"strings"
"github.com/influxdata/platform"
_ "github.com/influxdata/platform/query/builtin"
"github.com/influxdata/platform/query/control"
"github.com/influxdata/platform/query/execute"
"github.com/influxdata/platform/query/functions/storage"
ifqlid "github.com/influxdata/platform/query/id"
"github.com/influxdata/platform/query/repl"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
@ -69,3 +78,19 @@ func replF(cmd *cobra.Command, args []string) {
r.Run()
}
func getIFQLREPL(storageHosts storage.Reader, buckets platform.BucketService, org ifqlid.ID, verbose bool) (*repl.REPL, error) {
conf := control.Config{
ExecutorDependencies: make(execute.Dependencies),
ConcurrencyQuota: runtime.NumCPU() * 2,
MemoryBytesQuota: math.MaxInt64,
Verbose: verbose,
}
if err := injectDeps(conf.ExecutorDependencies, storageHosts, buckets); err != nil {
return nil, err
}
c := control.New(conf)
return repl.New(c, org), nil
}

21
query/builtin/builtin.go Normal file
View File

@ -0,0 +1,21 @@
// This package ensures all packages related to built-ins are imported and initialized.
// It provides helper functions for constructing various types that depend on the built-ins.
package query
import (
"github.com/influxdata/platform/query"
"github.com/influxdata/platform/query/complete"
_ "github.com/influxdata/platform/query/functions" // Import the built-in functions
"github.com/influxdata/platform/query/interpreter"
)
func init() {
query.FinalizeBuiltIns()
}
// DefaultCompleter creates a completer with builtin scope and declarations
func DefaultCompleter() complete.Completer {
scope, declarations := query.BuiltIns()
interpScope := interpreter.NewScopeWithValues(scope)
return complete.NewCompleter(interpScope, declarations)
}

View File

@ -111,29 +111,16 @@ func RegisterBuiltInValue(name string, v values.Value) {
builtinScope[name] = v
}
// FinalizeRegistration must be called to complete registration.
// FinalizeBuiltIns must be called to complete registration.
// Future calls to RegisterFunction, RegisterBuiltIn or RegisterBuiltInValue will panic.
func FinalizeRegistration() {
func FinalizeBuiltIns() {
if finalized {
panic("already finalized")
}
finalized = true
//for name, script := range builtins {
// astProg, err := parser.NewAST(script)
// if err != nil {
// panic(errors.Wrapf(err, "failed to parse builtin %q", name))
// }
// semProg, err := semantic.New(astProg, builtinDeclarations)
// if err != nil {
// panic(errors.Wrapf(err, "failed to create semantic graph for builtin %q", name))
// }
// if err := interpreter.Eval(semProg, builtinScope); err != nil {
// panic(errors.Wrapf(err, "failed to evaluate builtin %q", name))
// }
//}
//// free builtins list
//builtins = nil
// Call BuiltIns to validate all built-in values are valid.
// A panic will occur if any value is invalid.
_, _ = BuiltIns()
}
var TableObjectType = semantic.NewObjectType(map[string]semantic.Type{
@ -267,6 +254,9 @@ func DefaultFunctionSignature() semantic.FunctionSignature {
}
func BuiltIns() (map[string]values.Value, semantic.DeclarationScope) {
if !finalized {
panic("builtins not finalized")
}
qd := new(queryDomain)
return builtIns(qd)
}

View File

@ -5,7 +5,6 @@ import (
"fmt"
"sort"
"github.com/influxdata/platform/query"
"github.com/influxdata/platform/query/interpreter"
"github.com/influxdata/platform/query/semantic"
)
@ -96,10 +95,3 @@ func (c Completer) FunctionSuggestion(name string) (FunctionSuggestion, error) {
func isFunction(d semantic.VariableDeclaration) bool {
return d.InitType().Kind() == semantic.Function
}
// DefaultCompleter create a completer with builtin scope and declarations
func DefaultCompleter() Completer {
scope, declarations := query.BuiltIns()
interpScope := interpreter.NewScopeWithValues(scope)
return NewCompleter(interpScope, declarations)
}

View File

@ -1,33 +1,22 @@
package complete
package complete_test
import (
"testing"
"github.com/google/go-cmp/cmp"
_ "github.com/influxdata/platform/query/functions"
"github.com/influxdata/platform/query/complete"
"github.com/influxdata/platform/query/interpreter"
"github.com/influxdata/platform/query"
"github.com/influxdata/platform/query/semantic"
"github.com/influxdata/platform/query/values"
)
var scope *interpreter.Scope
var declarations semantic.DeclarationScope
func init() {
query.FinalizeRegistration()
s, d := query.BuiltIns()
scope = interpreter.NewScopeWithValues(s)
declarations = d
}
func TestNames(t *testing.T) {
s := interpreter.NewScope()
var v values.Value
s.Set("boom", v)
s.Set("tick", v)
c := NewCompleter(s, semantic.DeclarationScope{})
c := complete.NewCompleter(s, semantic.DeclarationScope{})
results := c.Names()
expected := []string{
@ -41,10 +30,15 @@ func TestNames(t *testing.T) {
}
func TestDeclaration(t *testing.T) {
name := "range"
name := "foo"
scope := interpreter.NewScope()
scope.Set(name, values.NewIntValue(5))
declarations := make(semantic.DeclarationScope)
declarations[name] = semantic.NewExternalVariableDeclaration(name, semantic.Int)
expected := declarations[name].ID()
declaration, _ := NewCompleter(scope, declarations).Declaration(name)
declaration, _ := complete.NewCompleter(scope, declarations).Declaration(name)
result := declaration.ID()
if !cmp.Equal(result, expected) {
@ -60,7 +54,7 @@ func TestFunctionNames(t *testing.T) {
d["noBoom"] = semantic.NewExternalVariableDeclaration("noBoom", semantic.String)
s := interpreter.NewScope()
c := NewCompleter(s, d)
c := complete.NewCompleter(s, d)
results := c.FunctionNames()
expected := []string{
@ -73,14 +67,26 @@ func TestFunctionNames(t *testing.T) {
}
func TestFunctionSuggestion(t *testing.T) {
name := "range"
result, _ := NewCompleter(scope, declarations).FunctionSuggestion(name)
name := "bar"
scope := interpreter.NewScope()
declarations := make(semantic.DeclarationScope)
declarations[name] = semantic.NewExternalVariableDeclaration(
name,
semantic.NewFunctionType(
semantic.FunctionSignature{
Params: map[string]semantic.Type{
"start": semantic.Time,
"stop": semantic.Time,
},
},
),
)
result, _ := complete.NewCompleter(scope, declarations).FunctionSuggestion(name)
expected := FunctionSuggestion{
expected := complete.FunctionSuggestion{
Params: map[string]string{
"start": semantic.Time.String(),
"stop": semantic.Time.String(),
"table": query.TableObjectType.Kind().String(),
},
}

View File

@ -9,6 +9,7 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/influxdata/platform/query"
"github.com/influxdata/platform/query/ast"
_ "github.com/influxdata/platform/query/builtin"
"github.com/influxdata/platform/query/execute"
"github.com/influxdata/platform/query/execute/executetest"
"github.com/influxdata/platform/query/functions"

View File

@ -6,6 +6,7 @@ import (
"github.com/gonum/stat/distuv"
"github.com/influxdata/platform/query"
_ "github.com/influxdata/platform/query/builtin"
"github.com/influxdata/platform/query/execute"
"github.com/influxdata/platform/query/execute/executetest"
"github.com/influxdata/platform/query/values"
@ -19,10 +20,6 @@ const (
seed = 42
)
func init() {
query.FinalizeRegistration()
}
// NormalData is a slice of N random values that are normaly distributed with mean Mu and standard deviation Sigma.
var NormalData []float64

View File

@ -11,6 +11,7 @@ import (
"strings"
"github.com/influxdata/platform/query"
_ "github.com/influxdata/platform/query/builtin"
"github.com/influxdata/platform/query/querytest"
"golang.org/x/text/unicode/norm"
@ -26,10 +27,6 @@ func printUsage() {
fmt.Println("usage: prepcsvtests /path/to/testfiles [testname]")
}
func init() {
query.FinalizeRegistration()
}
func main() {
fnames := make([]string, 0)
path := ""

View File

@ -8,6 +8,7 @@ import (
"testing"
"github.com/influxdata/platform/query"
_ "github.com/influxdata/platform/query/builtin"
"github.com/influxdata/platform/query/influxql"
"github.com/andreyvit/diff"