influxdb/query/influxql/end_to_end_test.go

282 lines
16 KiB
Go

package influxql_test
import (
"bufio"
"bytes"
"context"
platform2 "github.com/influxdata/influxdb/v2/kit/platform"
"io"
"io/ioutil"
"os"
"path/filepath"
"testing"
"github.com/influxdata/flux"
"github.com/influxdata/flux/execute"
"github.com/influxdata/flux/execute/executetest"
ifql "github.com/influxdata/flux/influxql"
"github.com/influxdata/flux/memory"
fluxquerytest "github.com/influxdata/flux/querytest"
platform "github.com/influxdata/influxdb/v2"
_ "github.com/influxdata/influxdb/v2/fluxinit/static"
"github.com/influxdata/influxdb/v2/mock"
"github.com/influxdata/influxdb/v2/query"
"github.com/influxdata/influxdb/v2/query/influxql"
"github.com/influxdata/influxdb/v2/query/querytest"
platformtesting "github.com/influxdata/influxdb/v2/testing"
)
const generatedInfluxQLDataDir = "testdata"
var dbrpMappingSvcE2E = &mock.DBRPMappingServiceV2{}
func init() {
mapping := platform.DBRPMappingV2{
Database: "db0",
RetentionPolicy: "autogen",
Default: true,
OrganizationID: platformtesting.MustIDBase16("cadecadecadecade"),
BucketID: platformtesting.MustIDBase16("da7aba5e5eedca5e"),
}
dbrpMappingSvcE2E.FindByIDFn = func(ctx context.Context, orgID, id platform2.ID) (*platform.DBRPMappingV2, error) {
return &mapping, nil
}
dbrpMappingSvcE2E.FindManyFn = func(ctx context.Context, filter platform.DBRPMappingFilterV2, opt ...platform.FindOptions) ([]*platform.DBRPMappingV2, int, error) {
return []*platform.DBRPMappingV2{&mapping}, 1, nil
}
}
var skipTests = map[string]string{
"hardcoded_literal_1": "transpiler count query is off by 1 https://github.com/influxdata/influxdb/issues/10744",
"hardcoded_literal_3": "transpiler count query is off by 1 https://github.com/influxdata/influxdb/issues/10744",
"fuzz_join_within_cursor": "transpiler does not implement joining fields within a cursor https://github.com/influxdata/influxdb/issues/10743",
"derivative_count": "add derivative support to the transpiler https://github.com/influxdata/influxdb/issues/10759",
"derivative_first": "add derivative support to the transpiler https://github.com/influxdata/influxdb/issues/10759",
"derivative_last": "add derivative support to the transpiler https://github.com/influxdata/influxdb/issues/10759",
"derivative_max": "add derivative support to the transpiler https://github.com/influxdata/influxdb/issues/10759",
"derivative_mean": "add derivative support to the transpiler https://github.com/influxdata/influxdb/issues/10759",
"derivative_median": "add derivative support to the transpiler https://github.com/influxdata/influxdb/issues/10759",
"derivative_min": "add derivative support to the transpiler https://github.com/influxdata/influxdb/issues/10759",
"derivative_mode": "add derivative support to the transpiler https://github.com/influxdata/influxdb/issues/10759",
"derivative_percentile_10": "add derivative support to the transpiler https://github.com/influxdata/influxdb/issues/10759",
"derivative_percentile_50": "add derivative support to the transpiler https://github.com/influxdata/influxdb/issues/10759",
"derivative_percentile_90": "add derivative support to the transpiler https://github.com/influxdata/influxdb/issues/10759",
"derivative_sum": "add derivative support to the transpiler https://github.com/influxdata/influxdb/issues/10759",
"regex_measurement_0": "Transpiler: regex on measurements not evaluated https://github.com/influxdata/influxdb/issues/10740",
"regex_measurement_1": "Transpiler: regex on measurements not evaluated https://github.com/influxdata/influxdb/issues/10740",
"regex_measurement_2": "Transpiler: regex on measurements not evaluated https://github.com/influxdata/influxdb/issues/10740",
"regex_measurement_3": "Transpiler: regex on measurements not evaluated https://github.com/influxdata/influxdb/issues/10740",
"regex_measurement_4": "Transpiler: regex on measurements not evaluated https://github.com/influxdata/influxdb/issues/10740",
"regex_measurement_5": "Transpiler: regex on measurements not evaluated https://github.com/influxdata/influxdb/issues/10740",
"regex_tag_0": "Transpiler: Returns results in wrong sort order for regex filter on tags https://github.com/influxdata/influxdb/issues/10739",
"regex_tag_1": "Transpiler: Returns results in wrong sort order for regex filter on tags https://github.com/influxdata/influxdb/issues/10739",
"regex_tag_2": "Transpiler: Returns results in wrong sort order for regex filter on tags https://github.com/influxdata/influxdb/issues/10739",
"regex_tag_3": "Transpiler: Returns results in wrong sort order for regex filter on tags https://github.com/influxdata/influxdb/issues/10739",
"explicit_type_0": "Transpiler should remove _start column https://github.com/influxdata/influxdb/issues/10742",
"explicit_type_1": "Transpiler should remove _start column https://github.com/influxdata/influxdb/issues/10742",
"fills_0": "need fill/Interpolate function https://github.com/influxdata/flux/issues/436",
"random_math_0": "transpiler does not implement joining fields within a cursor https://github.com/influxdata/influxdb/issues/10743",
"selector_0": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"selector_1": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"selector_2": "Transpiler: first function uses different series than influxQL https://github.com/influxdata/influxdb/issues/10737",
"selector_6": "Transpiler: first function uses different series than influxQL https://github.com/influxdata/influxdb/issues/10737",
"selector_7": "Transpiler: first function uses different series than influxQL https://github.com/influxdata/influxdb/issues/10737",
"series_agg_3": "Transpiler: Implement elapsed https://github.com/influxdata/influxdb/issues/10733",
"series_agg_4": "Transpiler: Implement cumulative_sum https://github.com/influxdata/influxdb/issues/10732",
"series_agg_5": "add derivative support to the transpiler https://github.com/influxdata/influxdb/issues/10759",
"series_agg_6": "Transpiler: Implement non_negative_derivative https://github.com/influxdata/influxdb/issues/10731",
"Subquery_0": "Implement subqueries in the transpiler https://github.com/influxdata/influxdb/issues/10660",
"Subquery_1": "Implement subqueries in the transpiler https://github.com/influxdata/influxdb/issues/10660",
"Subquery_2": "Implement subqueries in the transpiler https://github.com/influxdata/influxdb/issues/10660",
"Subquery_3": "Implement subqueries in the transpiler https://github.com/influxdata/influxdb/issues/10660",
"Subquery_4": "Implement subqueries in the transpiler https://github.com/influxdata/influxdb/issues/10660",
"Subquery_5": "Implement subqueries in the transpiler https://github.com/influxdata/influxdb/issues/10660",
"NestedSubquery_0": "Implement subqueries in the transpiler https://github.com/influxdata/influxdb/issues/10660",
"NestedSubquery_1": "Implement subqueries in the transpiler https://github.com/influxdata/influxdb/issues/10660",
"NestedSubquery_2": "Implement subqueries in the transpiler https://github.com/influxdata/influxdb/issues/10660",
"NestedSubquery_3": "Implement subqueries in the transpiler https://github.com/influxdata/influxdb/issues/10660",
"SimulatedHTTP_0": "Implement subqueries in the transpiler https://github.com/influxdata/influxdb/issues/10660",
"SimulatedHTTP_1": "Implement subqueries in the transpiler https://github.com/influxdata/influxdb/issues/10660",
"SimulatedHTTP_2": "Implement subqueries in the transpiler https://github.com/influxdata/influxdb/issues/10660",
"SimulatedHTTP_3": "Implement subqueries in the transpiler https://github.com/influxdata/influxdb/issues/10660",
"SimulatedHTTP_4": "Implement subqueries in the transpiler https://github.com/influxdata/influxdb/issues/10660",
"SelectorMath_0": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_1": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_2": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_3": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_4": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_5": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_6": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_7": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_8": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_9": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_10": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_11": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_12": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_13": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_14": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_15": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_16": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_17": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_18": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_19": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_20": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_21": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_22": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_23": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_24": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_25": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_26": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_27": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_28": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_29": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_30": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"SelectorMath_31": "Transpiler: unimplemented functions: top and bottom https://github.com/influxdata/influxdb/issues/10738",
"ands": "algo-w: https://github.com/influxdata/influxdb/issues/16811",
"ors": "algo-w: https://github.com/influxdata/influxdb/issues/16811",
}
var querier = fluxquerytest.NewQuerier()
func withEachInfluxQLFile(t testing.TB, fn func(prefix, caseName string)) {
dir, err := os.Getwd()
if err != nil {
t.Fatal(err)
}
path := filepath.Join(dir, generatedInfluxQLDataDir)
influxqlFiles, err := filepath.Glob(filepath.Join(path, "*.influxql"))
if err != nil {
t.Fatalf("error searching for influxQL files: %s", err)
}
for _, influxqlFile := range influxqlFiles {
ext := filepath.Ext(influxqlFile)
prefix := influxqlFile[0 : len(influxqlFile)-len(ext)]
_, caseName := filepath.Split(prefix)
fn(prefix, caseName)
}
}
func Test_GeneratedInfluxQLQueries(t *testing.T) {
withEachInfluxQLFile(t, func(prefix, caseName string) {
reason, skip := skipTests[caseName]
influxqlName := caseName + ".influxql"
t.Run(influxqlName, func(t *testing.T) {
if skip {
t.Skip(reason)
}
testGeneratedInfluxQL(t, prefix, ".influxql")
})
})
}
func testGeneratedInfluxQL(t testing.TB, prefix, queryExt string) {
q, err := ioutil.ReadFile(prefix + queryExt)
if err != nil {
if !os.IsNotExist(err) {
t.Fatal(err)
}
t.Skip("influxql query is missing")
}
inFile := prefix + ".in.json"
outFile := prefix + ".out.json"
out, err := jsonToResultIterator(outFile)
if err != nil {
t.Fatalf("failed to read expected JSON results: %v", err)
}
defer out.Release()
var exp []flux.Result
for out.More() {
exp = append(exp, out.Next())
}
res, err := resultsFromQuerier(querier, influxQLCompiler(string(q), inFile))
if err != nil {
t.Fatalf("failed to run query: %v", err)
}
defer res.Release()
var got []flux.Result
for res.More() {
got = append(got, res.Next())
}
if err := executetest.EqualResults(exp, got); err != nil {
t.Errorf("result not as expected: %v", err)
expBuffer := new(bytes.Buffer)
for _, e := range exp {
e.Tables().Do(func(tbl flux.Table) error {
_, err := execute.NewFormatter(tbl, nil).WriteTo(expBuffer)
return err
})
}
gotBuffer := new(bytes.Buffer)
for _, e := range got {
e.Tables().Do(func(tbl flux.Table) error {
_, err := execute.NewFormatter(tbl, nil).WriteTo(gotBuffer)
return err
})
}
t.Logf("\nExpected Tables:\n%s\nActualTables:\n%s\n", expBuffer.String(), gotBuffer.String())
}
}
func resultsFromQuerier(querier *fluxquerytest.Querier, compiler flux.Compiler) (flux.ResultIterator, error) {
req := &query.ProxyRequest{
Request: query.Request{
Compiler: compiler,
},
Dialect: new(influxql.Dialect),
}
jsonBuf, err := queryToJSON(querier, req)
if err != nil {
return nil, err
}
decoder := ifql.NewResultDecoder(new(memory.Allocator))
return decoder.Decode(ioutil.NopCloser(jsonBuf))
}
func influxQLCompiler(query, filename string) flux.Compiler {
compiler := influxql.NewCompiler(dbrpMappingSvcE2E)
compiler.Cluster = "cluster"
compiler.DB = "db0"
compiler.Query = query
querytest.MakeFromInfluxJSONCompiler(compiler, filename)
return compiler
}
func queryToJSON(querier *fluxquerytest.Querier, req *query.ProxyRequest) (io.ReadCloser, error) {
var buf bytes.Buffer
_, err := querier.Query(context.Background(), &buf, req.Request.Compiler, req.Dialect)
if err != nil {
return nil, err
}
return ioutil.NopCloser(&buf), nil
}
func jsonToResultIterator(file string) (flux.ResultIterator, error) {
f, err := os.Open(file)
if err != nil {
return nil, err
}
// Reader for influxql json file
jsonReader := bufio.NewReaderSize(f, 8196)
// InfluxQL json -> Flux tables decoder
decoder := ifql.NewResultDecoder(new(memory.Allocator))
// Decode json into Flux tables
results, err := decoder.Decode(ioutil.NopCloser(jsonReader))
if err != nil {
return nil, err
}
return results, nil
}