2017-08-15 19:24:22 +00:00
package query_test
2016-03-31 22:12:29 +00:00
import (
"errors"
"fmt"
2016-10-28 20:44:33 +00:00
"strings"
2016-03-31 22:12:29 +00:00
"testing"
"time"
2017-08-15 19:24:22 +00:00
"github.com/influxdata/influxdb/query"
2017-10-30 21:40:26 +00:00
"github.com/influxdata/influxql"
2016-03-31 22:12:29 +00:00
)
var errUnexpected = errors . New ( "unexpected error" )
type StatementExecutor struct {
2018-03-02 16:59:40 +00:00
ExecuteStatementFn func ( stmt influxql . Statement , ctx * query . ExecutionContext ) error
2016-03-31 22:12:29 +00:00
}
2021-02-12 16:50:26 +00:00
func ( e * StatementExecutor ) ExecuteStatement ( ctx * query . ExecutionContext , stmt influxql . Statement ) error {
2016-03-31 22:12:29 +00:00
return e . ExecuteStatementFn ( stmt , ctx )
}
2021-08-24 18:27:10 +00:00
type StatementNormalizerExecutor struct {
StatementExecutor
NormalizeStatementFn func ( stmt influxql . Statement , database , retentionPolicy string ) error
}
func ( e * StatementNormalizerExecutor ) NormalizeStatement ( stmt influxql . Statement , database , retentionPolicy string ) error {
return e . NormalizeStatementFn ( stmt , database , retentionPolicy )
}
2018-03-02 05:11:32 +00:00
func NewQueryExecutor ( ) * query . Executor {
return query . NewExecutor ( )
2016-03-31 22:12:29 +00:00
}
func TestQueryExecutor_AttachQuery ( t * testing . T ) {
q , err := influxql . ParseQuery ( ` SELECT count(value) FROM cpu ` )
if err != nil {
t . Fatal ( err )
}
2016-06-10 17:30:49 +00:00
e := NewQueryExecutor ( )
2016-03-31 22:12:29 +00:00
e . StatementExecutor = & StatementExecutor {
2018-03-02 16:59:40 +00:00
ExecuteStatementFn : func ( stmt influxql . Statement , ctx * query . ExecutionContext ) error {
2016-03-31 22:12:29 +00:00
if ctx . QueryID != 1 {
t . Errorf ( "incorrect query id: exp=1 got=%d" , ctx . QueryID )
}
return nil
} ,
}
2017-08-15 19:24:22 +00:00
discardOutput ( e . ExecuteQuery ( q , query . ExecutionOptions { } , nil ) )
2016-03-31 22:12:29 +00:00
}
func TestQueryExecutor_KillQuery ( t * testing . T ) {
q , err := influxql . ParseQuery ( ` SELECT count(value) FROM cpu ` )
if err != nil {
t . Fatal ( err )
}
qid := make ( chan uint64 )
2016-06-10 17:30:49 +00:00
e := NewQueryExecutor ( )
2016-03-31 22:12:29 +00:00
e . StatementExecutor = & StatementExecutor {
2018-03-02 16:59:40 +00:00
ExecuteStatementFn : func ( stmt influxql . Statement , ctx * query . ExecutionContext ) error {
2016-06-10 17:30:49 +00:00
switch stmt . ( type ) {
case * influxql . KillQueryStatement :
2021-02-12 16:50:26 +00:00
return e . TaskManager . ExecuteStatement ( ctx , stmt )
2016-06-10 17:30:49 +00:00
}
2016-03-31 22:12:29 +00:00
qid <- ctx . QueryID
select {
2018-03-02 16:59:40 +00:00
case <- ctx . Done ( ) :
return ctx . Err ( )
2016-03-31 22:12:29 +00:00
case <- time . After ( 100 * time . Millisecond ) :
t . Error ( "killing the query did not close the channel after 100 milliseconds" )
return errUnexpected
}
} ,
}
2017-08-15 19:24:22 +00:00
results := e . ExecuteQuery ( q , query . ExecutionOptions { } , nil )
2016-03-31 22:12:29 +00:00
q , err = influxql . ParseQuery ( fmt . Sprintf ( "KILL QUERY %d" , <- qid ) )
if err != nil {
t . Fatal ( err )
}
2017-08-15 19:24:22 +00:00
discardOutput ( e . ExecuteQuery ( q , query . ExecutionOptions { } , nil ) )
2016-03-31 22:12:29 +00:00
result := <- results
2017-08-15 19:24:22 +00:00
if result . Err != query . ErrQueryInterrupted {
2016-03-31 22:12:29 +00:00
t . Errorf ( "unexpected error: %s" , result . Err )
}
}
2017-09-19 19:17:23 +00:00
func TestQueryExecutor_KillQuery_Zombie ( t * testing . T ) {
q , err := influxql . ParseQuery ( ` SELECT count(value) FROM cpu ` )
if err != nil {
t . Fatal ( err )
}
qid := make ( chan uint64 )
done := make ( chan struct { } )
e := NewQueryExecutor ( )
e . StatementExecutor = & StatementExecutor {
2018-03-02 16:59:40 +00:00
ExecuteStatementFn : func ( stmt influxql . Statement , ctx * query . ExecutionContext ) error {
2017-09-19 19:17:23 +00:00
switch stmt . ( type ) {
case * influxql . KillQueryStatement , * influxql . ShowQueriesStatement :
2021-02-12 16:50:26 +00:00
return e . TaskManager . ExecuteStatement ( ctx , stmt )
2017-09-19 19:17:23 +00:00
}
qid <- ctx . QueryID
select {
2018-03-02 16:59:40 +00:00
case <- ctx . Done ( ) :
2017-09-19 19:17:23 +00:00
select {
case <- done :
// Keep the query running until we run SHOW QUERIES.
case <- time . After ( 100 * time . Millisecond ) :
// Ensure that we don't have a lingering goroutine.
}
return query . ErrQueryInterrupted
case <- time . After ( 100 * time . Millisecond ) :
t . Error ( "killing the query did not close the channel after 100 milliseconds" )
return errUnexpected
}
} ,
}
results := e . ExecuteQuery ( q , query . ExecutionOptions { } , nil )
q , err = influxql . ParseQuery ( fmt . Sprintf ( "KILL QUERY %d" , <- qid ) )
if err != nil {
t . Fatal ( err )
}
discardOutput ( e . ExecuteQuery ( q , query . ExecutionOptions { } , nil ) )
// Display the queries and ensure that the original is still in there.
q , err = influxql . ParseQuery ( "SHOW QUERIES" )
if err != nil {
t . Fatal ( err )
}
tasks := e . ExecuteQuery ( q , query . ExecutionOptions { } , nil )
// The killed query should still be there.
task := <- tasks
if len ( task . Series ) != 1 {
t . Errorf ( "expected %d series, got %d" , 1 , len ( task . Series ) )
} else if len ( task . Series [ 0 ] . Values ) != 2 {
t . Errorf ( "expected %d rows, got %d" , 2 , len ( task . Series [ 0 ] . Values ) )
}
close ( done )
// The original query should return.
result := <- results
if result . Err != query . ErrQueryInterrupted {
t . Errorf ( "unexpected error: %s" , result . Err )
}
}
2017-10-26 16:31:18 +00:00
func TestQueryExecutor_KillQuery_CloseTaskManager ( t * testing . T ) {
q , err := influxql . ParseQuery ( ` SELECT count(value) FROM cpu ` )
if err != nil {
t . Fatal ( err )
}
qid := make ( chan uint64 )
// Open a channel to stall the statement executor forever. This keeps the statement executor
// running even after we kill the query which can happen with some queries. We only close it once
// the test has finished running.
done := make ( chan struct { } )
defer close ( done )
e := NewQueryExecutor ( )
e . StatementExecutor = & StatementExecutor {
2018-03-02 16:59:40 +00:00
ExecuteStatementFn : func ( stmt influxql . Statement , ctx * query . ExecutionContext ) error {
2017-10-26 16:31:18 +00:00
switch stmt . ( type ) {
case * influxql . KillQueryStatement , * influxql . ShowQueriesStatement :
2021-02-12 16:50:26 +00:00
return e . TaskManager . ExecuteStatement ( ctx , stmt )
2017-10-26 16:31:18 +00:00
}
qid <- ctx . QueryID
<- done
return nil
} ,
}
// Kill the query. This should switch it into a zombie state.
go discardOutput ( e . ExecuteQuery ( q , query . ExecutionOptions { } , nil ) )
q , err = influxql . ParseQuery ( fmt . Sprintf ( "KILL QUERY %d" , <- qid ) )
if err != nil {
t . Fatal ( err )
}
discardOutput ( e . ExecuteQuery ( q , query . ExecutionOptions { } , nil ) )
// Display the queries and ensure that the original is still in there.
q , err = influxql . ParseQuery ( "SHOW QUERIES" )
if err != nil {
t . Fatal ( err )
}
tasks := e . ExecuteQuery ( q , query . ExecutionOptions { } , nil )
// The killed query should still be there.
task := <- tasks
if len ( task . Series ) != 1 {
t . Errorf ( "expected %d series, got %d" , 1 , len ( task . Series ) )
} else if len ( task . Series [ 0 ] . Values ) != 2 {
t . Errorf ( "expected %d rows, got %d" , 2 , len ( task . Series [ 0 ] . Values ) )
}
// Close the task manager to ensure it doesn't cause a panic.
if err := e . TaskManager . Close ( ) ; err != nil {
t . Errorf ( "unexpected error: %s" , err )
}
}
func TestQueryExecutor_KillQuery_AlreadyKilled ( t * testing . T ) {
q , err := influxql . ParseQuery ( ` SELECT count(value) FROM cpu ` )
if err != nil {
t . Fatal ( err )
}
qid := make ( chan uint64 )
// Open a channel to stall the statement executor forever. This keeps the statement executor
// running even after we kill the query which can happen with some queries. We only close it once
// the test has finished running.
done := make ( chan struct { } )
defer close ( done )
e := NewQueryExecutor ( )
e . StatementExecutor = & StatementExecutor {
2018-03-02 16:59:40 +00:00
ExecuteStatementFn : func ( stmt influxql . Statement , ctx * query . ExecutionContext ) error {
2017-10-26 16:31:18 +00:00
switch stmt . ( type ) {
case * influxql . KillQueryStatement , * influxql . ShowQueriesStatement :
2021-02-12 16:50:26 +00:00
return e . TaskManager . ExecuteStatement ( ctx , stmt )
2017-10-26 16:31:18 +00:00
}
qid <- ctx . QueryID
<- done
return nil
} ,
}
// Kill the query. This should switch it into a zombie state.
go discardOutput ( e . ExecuteQuery ( q , query . ExecutionOptions { } , nil ) )
q , err = influxql . ParseQuery ( fmt . Sprintf ( "KILL QUERY %d" , <- qid ) )
if err != nil {
t . Fatal ( err )
}
discardOutput ( e . ExecuteQuery ( q , query . ExecutionOptions { } , nil ) )
// Now attempt to kill it again. We should get an error.
results := e . ExecuteQuery ( q , query . ExecutionOptions { } , nil )
result := <- results
if got , want := result . Err , query . ErrAlreadyKilled ; got != want {
t . Errorf ( "unexpected error: got=%v want=%v" , got , want )
}
}
2016-03-31 22:12:29 +00:00
func TestQueryExecutor_Interrupt ( t * testing . T ) {
q , err := influxql . ParseQuery ( ` SELECT count(value) FROM cpu ` )
if err != nil {
t . Fatal ( err )
}
2016-06-10 17:30:49 +00:00
e := NewQueryExecutor ( )
2016-03-31 22:12:29 +00:00
e . StatementExecutor = & StatementExecutor {
2018-03-02 16:59:40 +00:00
ExecuteStatementFn : func ( stmt influxql . Statement , ctx * query . ExecutionContext ) error {
2016-03-31 22:12:29 +00:00
select {
2018-03-02 16:59:40 +00:00
case <- ctx . Done ( ) :
return ctx . Err ( )
2016-03-31 22:12:29 +00:00
case <- time . After ( 100 * time . Millisecond ) :
t . Error ( "killing the query did not close the channel after 100 milliseconds" )
return errUnexpected
}
} ,
}
closing := make ( chan struct { } )
2017-08-15 19:24:22 +00:00
results := e . ExecuteQuery ( q , query . ExecutionOptions { } , closing )
2016-03-31 22:12:29 +00:00
close ( closing )
result := <- results
2017-08-15 19:24:22 +00:00
if result . Err != query . ErrQueryInterrupted {
2016-03-31 22:12:29 +00:00
t . Errorf ( "unexpected error: %s" , result . Err )
}
}
2016-11-08 19:12:25 +00:00
func TestQueryExecutor_Abort ( t * testing . T ) {
q , err := influxql . ParseQuery ( ` SELECT count(value) FROM cpu ` )
if err != nil {
t . Fatal ( err )
}
ch1 := make ( chan struct { } )
ch2 := make ( chan struct { } )
e := NewQueryExecutor ( )
e . StatementExecutor = & StatementExecutor {
2018-03-02 16:59:40 +00:00
ExecuteStatementFn : func ( stmt influxql . Statement , ctx * query . ExecutionContext ) error {
2016-11-08 19:12:25 +00:00
<- ch1
2017-08-15 19:24:22 +00:00
if err := ctx . Send ( & query . Result { Err : errUnexpected } ) ; err != query . ErrQueryAborted {
2016-11-08 19:12:25 +00:00
t . Errorf ( "unexpected error: %v" , err )
}
close ( ch2 )
return nil
} ,
}
done := make ( chan struct { } )
close ( done )
2017-08-15 19:24:22 +00:00
results := e . ExecuteQuery ( q , query . ExecutionOptions { AbortCh : done } , nil )
2016-11-08 19:12:25 +00:00
close ( ch1 )
<- ch2
discardOutput ( results )
}
2016-03-31 22:12:29 +00:00
func TestQueryExecutor_ShowQueries ( t * testing . T ) {
2016-06-10 17:30:49 +00:00
e := NewQueryExecutor ( )
2016-03-31 22:12:29 +00:00
e . StatementExecutor = & StatementExecutor {
2018-03-02 16:59:40 +00:00
ExecuteStatementFn : func ( stmt influxql . Statement , ctx * query . ExecutionContext ) error {
2016-06-10 17:30:49 +00:00
switch stmt . ( type ) {
case * influxql . ShowQueriesStatement :
2021-02-12 16:50:26 +00:00
return e . TaskManager . ExecuteStatement ( ctx , stmt )
2016-06-10 17:30:49 +00:00
}
2016-03-31 22:12:29 +00:00
t . Errorf ( "unexpected statement: %s" , stmt )
return errUnexpected
} ,
}
2016-12-29 19:13:48 +00:00
q , err := influxql . ParseQuery ( ` SHOW QUERIES ` )
2016-03-31 22:12:29 +00:00
if err != nil {
t . Fatal ( err )
}
2017-08-15 19:24:22 +00:00
results := e . ExecuteQuery ( q , query . ExecutionOptions { } , nil )
2016-03-31 22:12:29 +00:00
result := <- results
if len ( result . Series ) != 1 {
2017-09-19 19:17:23 +00:00
t . Errorf ( "expected %d series, got %d" , 1 , len ( result . Series ) )
} else if len ( result . Series [ 0 ] . Values ) != 1 {
t . Errorf ( "expected %d row, got %d" , 1 , len ( result . Series [ 0 ] . Values ) )
2016-03-31 22:12:29 +00:00
}
if result . Err != nil {
t . Errorf ( "unexpected error: %s" , result . Err )
}
}
func TestQueryExecutor_Limit_Timeout ( t * testing . T ) {
q , err := influxql . ParseQuery ( ` SELECT count(value) FROM cpu ` )
if err != nil {
t . Fatal ( err )
}
2016-06-10 17:30:49 +00:00
e := NewQueryExecutor ( )
2016-03-31 22:12:29 +00:00
e . StatementExecutor = & StatementExecutor {
2018-03-02 16:59:40 +00:00
ExecuteStatementFn : func ( stmt influxql . Statement , ctx * query . ExecutionContext ) error {
2016-03-31 22:12:29 +00:00
select {
2018-03-02 16:59:40 +00:00
case <- ctx . Done ( ) :
return ctx . Err ( )
2016-03-31 22:12:29 +00:00
case <- time . After ( time . Second ) :
t . Errorf ( "timeout has not killed the query" )
return errUnexpected
}
} ,
}
2016-06-10 17:30:49 +00:00
e . TaskManager . QueryTimeout = time . Nanosecond
2016-03-31 22:12:29 +00:00
2017-08-15 19:24:22 +00:00
results := e . ExecuteQuery ( q , query . ExecutionOptions { } , nil )
2016-03-31 22:12:29 +00:00
result := <- results
2016-10-28 20:44:33 +00:00
if result . Err == nil || ! strings . Contains ( result . Err . Error ( ) , "query-timeout" ) {
2016-03-31 22:12:29 +00:00
t . Errorf ( "unexpected error: %s" , result . Err )
}
}
func TestQueryExecutor_Limit_ConcurrentQueries ( t * testing . T ) {
q , err := influxql . ParseQuery ( ` SELECT count(value) FROM cpu ` )
if err != nil {
t . Fatal ( err )
}
qid := make ( chan uint64 )
2016-06-10 17:30:49 +00:00
e := NewQueryExecutor ( )
2016-03-31 22:12:29 +00:00
e . StatementExecutor = & StatementExecutor {
2018-03-02 16:59:40 +00:00
ExecuteStatementFn : func ( stmt influxql . Statement , ctx * query . ExecutionContext ) error {
2016-03-31 22:12:29 +00:00
qid <- ctx . QueryID
2018-03-02 16:59:40 +00:00
<- ctx . Done ( )
return ctx . Err ( )
2016-03-31 22:12:29 +00:00
} ,
}
2016-06-10 17:30:49 +00:00
e . TaskManager . MaxConcurrentQueries = 1
2016-03-31 22:12:29 +00:00
defer e . Close ( )
// Start first query and wait for it to be executing.
2017-08-15 19:24:22 +00:00
go discardOutput ( e . ExecuteQuery ( q , query . ExecutionOptions { } , nil ) )
2016-03-31 22:12:29 +00:00
<- qid
// Start second query and expect for it to fail.
2017-08-15 19:24:22 +00:00
results := e . ExecuteQuery ( q , query . ExecutionOptions { } , nil )
2016-03-31 22:12:29 +00:00
select {
case result := <- results :
if len ( result . Series ) != 0 {
t . Errorf ( "expected %d rows, got %d" , 0 , len ( result . Series ) )
}
2016-10-28 20:44:33 +00:00
if result . Err == nil || ! strings . Contains ( result . Err . Error ( ) , "max-concurrent-queries" ) {
2016-03-31 22:12:29 +00:00
t . Errorf ( "unexpected error: %s" , result . Err )
}
case <- qid :
t . Errorf ( "unexpected statement execution for the second query" )
}
}
func TestQueryExecutor_Close ( t * testing . T ) {
q , err := influxql . ParseQuery ( ` SELECT count(value) FROM cpu ` )
if err != nil {
t . Fatal ( err )
}
ch1 := make ( chan struct { } )
ch2 := make ( chan struct { } )
2016-06-10 17:30:49 +00:00
e := NewQueryExecutor ( )
2016-03-31 22:12:29 +00:00
e . StatementExecutor = & StatementExecutor {
2018-03-02 16:59:40 +00:00
ExecuteStatementFn : func ( stmt influxql . Statement , ctx * query . ExecutionContext ) error {
2016-03-31 22:12:29 +00:00
close ( ch1 )
2018-03-02 16:59:40 +00:00
<- ctx . Done ( )
return ctx . Err ( )
2016-03-31 22:12:29 +00:00
} ,
}
2017-08-15 19:24:22 +00:00
results := e . ExecuteQuery ( q , query . ExecutionOptions { } , nil )
go func ( results <- chan * query . Result ) {
2016-03-31 22:12:29 +00:00
result := <- results
2017-08-15 19:24:22 +00:00
if result . Err != query . ErrQueryEngineShutdown {
2016-03-31 22:12:29 +00:00
t . Errorf ( "unexpected error: %s" , result . Err )
}
2016-11-08 19:12:25 +00:00
close ( ch2 )
2016-03-31 22:12:29 +00:00
} ( results )
// Wait for the statement to start executing.
<- ch1
// Close the query executor.
e . Close ( )
// Check that the statement gets interrupted and finishes.
select {
case <- ch2 :
case <- time . After ( 100 * time . Millisecond ) :
2016-11-08 19:12:25 +00:00
t . Fatal ( "closing the query manager did not kill the query after 100 milliseconds" )
2016-03-31 22:12:29 +00:00
}
2017-08-15 19:24:22 +00:00
results = e . ExecuteQuery ( q , query . ExecutionOptions { } , nil )
2016-03-31 22:12:29 +00:00
result := <- results
if len ( result . Series ) != 0 {
t . Errorf ( "expected %d rows, got %d" , 0 , len ( result . Series ) )
}
2017-08-15 19:24:22 +00:00
if result . Err != query . ErrQueryEngineShutdown {
2016-03-31 22:12:29 +00:00
t . Errorf ( "unexpected error: %s" , result . Err )
}
}
2016-04-14 18:45:52 +00:00
func TestQueryExecutor_Panic ( t * testing . T ) {
q , err := influxql . ParseQuery ( ` SELECT count(value) FROM cpu ` )
if err != nil {
t . Fatal ( err )
}
2016-06-10 17:30:49 +00:00
e := NewQueryExecutor ( )
2016-04-14 18:45:52 +00:00
e . StatementExecutor = & StatementExecutor {
2018-03-02 16:59:40 +00:00
ExecuteStatementFn : func ( stmt influxql . Statement , ctx * query . ExecutionContext ) error {
2016-04-14 18:45:52 +00:00
panic ( "test error" )
} ,
}
2017-08-15 19:24:22 +00:00
results := e . ExecuteQuery ( q , query . ExecutionOptions { } , nil )
2016-04-14 18:45:52 +00:00
result := <- results
if len ( result . Series ) != 0 {
t . Errorf ( "expected %d rows, got %d" , 0 , len ( result . Series ) )
}
if result . Err == nil || result . Err . Error ( ) != "SELECT count(value) FROM cpu [panic:test error]" {
t . Errorf ( "unexpected error: %s" , result . Err )
}
}
2021-08-24 18:27:10 +00:00
const goodStatement = ` SELECT count(value) FROM cpu `
func TestQueryExecutor_NotExecuted ( t * testing . T ) {
var executorFailIndex int
var executorCallCount int
queryStatements := [ ] string { goodStatement , goodStatement , goodStatement , goodStatement , goodStatement }
queryStr := strings . Join ( queryStatements , ";" )
var closing chan struct { }
q , err := influxql . ParseQuery ( queryStr )
if err != nil {
t . Fatalf ( "parsing %s: %v" , queryStr , err )
}
e := NewQueryExecutor ( )
e . StatementExecutor = & StatementExecutor {
ExecuteStatementFn : func ( stmt influxql . Statement , ctx * query . ExecutionContext ) error {
defer func ( ) { executorCallCount ++ } ( )
if executorFailIndex == executorCallCount {
closing <- struct { } { }
close ( closing )
select {
case <- ctx . Done ( ) :
return nil
}
} else {
return ctx . Send ( & query . Result { Err : nil } )
}
} ,
}
testFn := func ( testName string , i int ) {
results := e . ExecuteQuery ( q , query . ExecutionOptions { } , closing )
checkNotExecutedResults ( t , results , testName , i , len ( q . Statements ) )
}
for i := 0 ; i < len ( q . Statements ) ; i ++ {
closing = make ( chan struct { } )
executorFailIndex = i
executorCallCount = 0
testFn ( "executor" , i )
}
}
func checkNotExecutedResults ( t * testing . T , results <- chan * query . Result , testName string , failIndex int , lenQuery int ) {
notExecutedIndex := failIndex + 1
for result := range results {
if result . Err == query . ErrNotExecuted {
if result . StatementID != notExecutedIndex {
t . Fatalf ( "StatementID for ErrNotExecuted in wrong order - expected: %d, got: %d" , notExecutedIndex , result . StatementID )
} else {
notExecutedIndex ++
}
}
}
if notExecutedIndex != lenQuery {
2021-08-31 21:43:12 +00:00
t . Fatalf ( "wrong number of results from %s with fail index of %d - got: %d, expected: %d" , testName , failIndex , notExecutedIndex - ( 1 + failIndex ) , lenQuery - ( 1 + failIndex ) )
2021-08-24 18:27:10 +00:00
}
}
2016-09-20 18:58:46 +00:00
func TestQueryExecutor_InvalidSource ( t * testing . T ) {
e := NewQueryExecutor ( )
e . StatementExecutor = & StatementExecutor {
2018-03-02 16:59:40 +00:00
ExecuteStatementFn : func ( stmt influxql . Statement , ctx * query . ExecutionContext ) error {
2016-09-20 18:58:46 +00:00
return errors . New ( "statement executed unexpectedly" )
} ,
}
for i , tt := range [ ] struct {
q string
err string
} {
{
q : ` SELECT fieldKey, fieldType FROM _fieldKeys ` ,
err : ` unable to use system source '_fieldKeys': use SHOW FIELD KEYS instead ` ,
} ,
{
q : ` SELECT "name" FROM _measurements ` ,
err : ` unable to use system source '_measurements': use SHOW MEASUREMENTS instead ` ,
} ,
{
q : ` SELECT "key" FROM _series ` ,
err : ` unable to use system source '_series': use SHOW SERIES instead ` ,
} ,
{
q : ` SELECT tagKey FROM _tagKeys ` ,
err : ` unable to use system source '_tagKeys': use SHOW TAG KEYS instead ` ,
} ,
{
q : ` SELECT "key", value FROM _tags ` ,
err : ` unable to use system source '_tags': use SHOW TAG VALUES instead ` ,
} ,
} {
q , err := influxql . ParseQuery ( tt . q )
if err != nil {
t . Errorf ( "%d. unable to parse: %s" , i , tt . q )
continue
}
2017-08-15 19:24:22 +00:00
results := e . ExecuteQuery ( q , query . ExecutionOptions { } , nil )
2016-09-20 18:58:46 +00:00
result := <- results
if len ( result . Series ) != 0 {
t . Errorf ( "%d. expected %d rows, got %d" , 0 , i , len ( result . Series ) )
}
if result . Err == nil || result . Err . Error ( ) != tt . err {
t . Errorf ( "%d. unexpected error: %s" , i , result . Err )
}
}
}
2017-08-15 19:24:22 +00:00
func discardOutput ( results <- chan * query . Result ) {
2016-03-31 22:12:29 +00:00
for range results {
// Read all results and discard.
}
}