2014-11-22 04:12:48 +00:00
package influxql_test
import (
2015-03-08 00:30:42 +00:00
"encoding/json"
2014-11-22 04:12:48 +00:00
"reflect"
2015-02-13 18:25:48 +00:00
"regexp"
2014-11-22 04:12:48 +00:00
"strings"
"testing"
"time"
"github.com/influxdb/influxdb/influxql"
)
2014-11-22 23:33:21 +00:00
// Ensure the parser can parse a multi-statement query.
func TestParser_ParseQuery ( t * testing . T ) {
s := ` SELECT a FROM b; SELECT c FROM d `
q , err := influxql . NewParser ( strings . NewReader ( s ) ) . ParseQuery ( )
if err != nil {
t . Fatalf ( "unexpected error: %s" , err )
} else if len ( q . Statements ) != 2 {
t . Fatalf ( "unexpected statement count: %d" , len ( q . Statements ) )
}
}
// Ensure the parser can parse an empty query.
func TestParser_ParseQuery_Empty ( t * testing . T ) {
q , err := influxql . NewParser ( strings . NewReader ( ` ` ) ) . ParseQuery ( )
if err != nil {
t . Fatalf ( "unexpected error: %s" , err )
} else if len ( q . Statements ) != 0 {
t . Fatalf ( "unexpected statement count: %d" , len ( q . Statements ) )
}
}
// Ensure the parser can return an error from an malformed statement.
func TestParser_ParseQuery_ParseError ( t * testing . T ) {
_ , err := influxql . NewParser ( strings . NewReader ( ` SELECT ` ) ) . ParseQuery ( )
if err == nil || err . Error ( ) != ` found EOF, expected identifier, string, number, bool at line 1, char 8 ` {
t . Fatalf ( "unexpected error: %s" , err )
}
}
2014-11-22 04:12:48 +00:00
// Ensure the parser can parse strings into Statement ASTs.
func TestParser_ParseStatement ( t * testing . T ) {
var tests = [ ] struct {
s string
stmt influxql . Statement
err string
} {
2014-11-25 23:23:10 +00:00
// SELECT * statement
{
s : ` SELECT * FROM myseries ` ,
stmt : & influxql . SelectStatement {
2015-01-12 19:43:38 +00:00
Fields : [ ] * influxql . Field {
2015-02-01 20:33:12 +00:00
{ Expr : & influxql . Wildcard { } } ,
2014-11-25 23:23:10 +00:00
} ,
2014-12-20 04:36:52 +00:00
Source : & influxql . Measurement { Name : "myseries" } ,
2014-11-25 23:23:10 +00:00
} ,
} ,
2014-11-22 23:33:21 +00:00
// SELECT statement
2014-11-22 04:12:48 +00:00
{
2015-01-25 20:34:49 +00:00
s : ` SELECT field1, field2 ,field3 AS field_x FROM myseries WHERE host = 'hosta.influxdb.org' GROUP BY 10h ORDER BY ASC LIMIT 20 OFFSET 10; ` ,
2014-11-22 04:12:48 +00:00
stmt : & influxql . SelectStatement {
2015-01-12 19:43:38 +00:00
Fields : [ ] * influxql . Field {
2015-02-01 20:33:12 +00:00
{ Expr : & influxql . VarRef { Val : "field1" } } ,
{ Expr : & influxql . VarRef { Val : "field2" } } ,
{ Expr : & influxql . VarRef { Val : "field3" } , Alias : "field_x" } ,
2014-11-22 04:12:48 +00:00
} ,
2014-12-20 04:36:52 +00:00
Source : & influxql . Measurement { Name : "myseries" } ,
2014-11-22 04:12:48 +00:00
Condition : & influxql . BinaryExpr {
Op : influxql . EQ ,
LHS : & influxql . VarRef { Val : "host" } ,
RHS : & influxql . StringLiteral { Val : "hosta.influxdb.org" } ,
} ,
2015-01-12 19:47:22 +00:00
Dimensions : [ ] * influxql . Dimension {
2015-02-01 20:33:12 +00:00
{ Expr : & influxql . DurationLiteral { Val : 10 * time . Hour } } ,
2014-11-22 04:12:48 +00:00
} ,
2015-01-12 19:47:22 +00:00
SortFields : [ ] * influxql . SortField {
2015-02-01 20:33:12 +00:00
{ Ascending : true } ,
2014-12-15 00:54:51 +00:00
} ,
2015-01-25 20:34:49 +00:00
Limit : 20 ,
Offset : 10 ,
2014-11-22 04:12:48 +00:00
} ,
} ,
2014-12-06 18:17:58 +00:00
// SELECT statement with JOIN
{
2015-01-19 23:01:24 +00:00
s : ` SELECT field1 FROM join(aa,"bb", cc) JOIN cc ` ,
2014-12-06 18:17:58 +00:00
stmt : & influxql . SelectStatement {
2015-02-01 20:33:12 +00:00
Fields : [ ] * influxql . Field { { Expr : & influxql . VarRef { Val : "field1" } } } ,
2014-12-06 18:17:58 +00:00
Source : & influxql . Join {
2015-01-12 19:47:22 +00:00
Measurements : [ ] * influxql . Measurement {
2014-12-20 04:36:52 +00:00
{ Name : "aa" } ,
2015-01-19 23:01:24 +00:00
{ Name : ` "bb" ` } ,
2014-12-20 04:36:52 +00:00
{ Name : "cc" } ,
2014-12-06 18:17:58 +00:00
} ,
} ,
} ,
} ,
// SELECT statement with MERGE
{
2014-12-20 04:36:52 +00:00
s : ` SELECT field1 FROM merge(aa,b.b) ` ,
2014-12-06 18:17:58 +00:00
stmt : & influxql . SelectStatement {
2015-02-01 20:33:12 +00:00
Fields : [ ] * influxql . Field { { Expr : & influxql . VarRef { Val : "field1" } } } ,
2014-12-06 18:17:58 +00:00
Source : & influxql . Merge {
2015-01-12 19:50:49 +00:00
Measurements : [ ] * influxql . Measurement {
2014-12-20 04:36:52 +00:00
{ Name : "aa" } ,
{ Name : "b.b" } ,
2014-12-06 18:17:58 +00:00
} ,
} ,
} ,
} ,
2014-11-25 01:14:03 +00:00
// SELECT statement (lowercase)
{
s : ` select my_field from myseries ` ,
stmt : & influxql . SelectStatement {
2015-02-01 20:33:12 +00:00
Fields : [ ] * influxql . Field { { Expr : & influxql . VarRef { Val : "my_field" } } } ,
2014-12-20 04:36:52 +00:00
Source : & influxql . Measurement { Name : "myseries" } ,
2014-11-25 01:14:03 +00:00
} ,
} ,
2014-12-15 00:54:51 +00:00
// SELECT statement with multiple ORDER BY fields
{
s : ` SELECT field1 FROM myseries ORDER BY ASC, field1, field2 DESC LIMIT 10 ` ,
stmt : & influxql . SelectStatement {
2015-02-01 20:33:12 +00:00
Fields : [ ] * influxql . Field { { Expr : & influxql . VarRef { Val : "field1" } } } ,
2014-12-20 04:36:52 +00:00
Source : & influxql . Measurement { Name : "myseries" } ,
2015-01-12 19:47:22 +00:00
SortFields : [ ] * influxql . SortField {
2015-02-01 20:33:12 +00:00
{ Ascending : true } ,
{ Name : "field1" } ,
{ Name : "field2" } ,
2014-12-15 00:54:51 +00:00
} ,
Limit : 10 ,
} ,
} ,
2015-03-03 02:21:37 +00:00
// SELECT * FROM cpu WHERE host = 'serverC' AND region =~ /.*west.*/
2015-03-02 16:33:51 +00:00
{
2015-03-03 02:21:37 +00:00
s : ` SELECT * FROM cpu WHERE host = 'serverC' AND region =~ /.*west.*/ ` ,
2015-03-02 16:33:51 +00:00
stmt : & influxql . SelectStatement {
Fields : [ ] * influxql . Field { { Expr : & influxql . Wildcard { } } } ,
Source : & influxql . Measurement { Name : "cpu" } ,
Condition : & influxql . BinaryExpr {
Op : influxql . AND ,
LHS : & influxql . BinaryExpr {
Op : influxql . EQ ,
LHS : & influxql . VarRef { Val : "host" } ,
RHS : & influxql . StringLiteral { Val : "serverC" } ,
} ,
RHS : & influxql . BinaryExpr {
Op : influxql . EQREGEX ,
LHS : & influxql . VarRef { Val : "region" } ,
RHS : & influxql . RegexLiteral { Val : regexp . MustCompile ( ".*west.*" ) } ,
} ,
} ,
} ,
} ,
2014-11-22 23:33:21 +00:00
// DELETE statement
{
s : ` DELETE FROM myseries WHERE host = 'hosta.influxdb.org' ` ,
stmt : & influxql . DeleteStatement {
2014-12-20 04:36:52 +00:00
Source : & influxql . Measurement { Name : "myseries" } ,
2014-11-22 23:33:21 +00:00
Condition : & influxql . BinaryExpr {
Op : influxql . EQ ,
LHS : & influxql . VarRef { Val : "host" } ,
RHS : & influxql . StringLiteral { Val : "hosta.influxdb.org" } ,
} ,
} ,
} ,
2015-01-26 03:40:50 +00:00
// SHOW DATABASES
2015-01-09 15:47:57 +00:00
{
2015-01-26 03:40:50 +00:00
s : ` SHOW DATABASES ` ,
stmt : & influxql . ShowDatabasesStatement { } ,
2015-01-09 15:47:57 +00:00
} ,
2015-01-26 03:40:50 +00:00
// SHOW SERIES statement
2014-11-22 23:33:21 +00:00
{
2015-01-26 03:40:50 +00:00
s : ` SHOW SERIES ` ,
stmt : & influxql . ShowSeriesStatement { } ,
2014-11-22 23:33:21 +00:00
} ,
2015-01-26 03:40:50 +00:00
// SHOW SERIES WHERE with ORDER BY and LIMIT
2014-12-10 14:37:15 +00:00
{
2015-01-26 03:40:50 +00:00
s : ` SHOW SERIES WHERE region = 'uswest' ORDER BY ASC, field1, field2 DESC LIMIT 10 ` ,
stmt : & influxql . ShowSeriesStatement {
2014-12-10 14:37:15 +00:00
Condition : & influxql . BinaryExpr {
2014-12-16 14:06:28 +00:00
Op : influxql . EQ ,
2014-12-16 02:48:22 +00:00
LHS : & influxql . VarRef { Val : "region" } ,
RHS : & influxql . StringLiteral { Val : "uswest" } ,
} ,
2015-01-12 19:47:22 +00:00
SortFields : [ ] * influxql . SortField {
2015-02-01 20:33:12 +00:00
{ Ascending : true } ,
{ Name : "field1" } ,
{ Name : "field2" } ,
2014-12-16 02:48:22 +00:00
} ,
Limit : 10 ,
} ,
} ,
2015-01-26 03:40:50 +00:00
// SHOW MEASUREMENTS WHERE with ORDER BY and LIMIT
2014-12-16 02:48:22 +00:00
{
2015-01-26 03:40:50 +00:00
s : ` SHOW MEASUREMENTS WHERE region = 'uswest' ORDER BY ASC, field1, field2 DESC LIMIT 10 ` ,
stmt : & influxql . ShowMeasurementsStatement {
2014-12-16 02:48:22 +00:00
Condition : & influxql . BinaryExpr {
2014-12-16 14:06:28 +00:00
Op : influxql . EQ ,
2014-12-16 02:48:22 +00:00
LHS : & influxql . VarRef { Val : "region" } ,
RHS : & influxql . StringLiteral { Val : "uswest" } ,
} ,
2015-01-12 19:47:22 +00:00
SortFields : [ ] * influxql . SortField {
2015-02-01 20:33:12 +00:00
{ Ascending : true } ,
{ Name : "field1" } ,
{ Name : "field2" } ,
2014-12-16 02:48:22 +00:00
} ,
Limit : 10 ,
} ,
} ,
2015-01-26 03:40:50 +00:00
// SHOW RETENTION POLICIES
2015-01-13 20:21:06 +00:00
{
2015-01-26 03:40:50 +00:00
s : ` SHOW RETENTION POLICIES mydb ` ,
stmt : & influxql . ShowRetentionPoliciesStatement {
2015-01-13 20:21:06 +00:00
Database : "mydb" ,
} ,
} ,
2015-01-29 01:26:15 +00:00
// SHOW TAG KEYS
{
s : ` SHOW TAG KEYS FROM src ` ,
stmt : & influxql . ShowTagKeysStatement {
Source : & influxql . Measurement { Name : "src" } ,
} ,
} ,
2015-01-26 03:40:50 +00:00
// SHOW TAG KEYS
2014-12-16 02:48:22 +00:00
{
2015-01-26 03:40:50 +00:00
s : ` SHOW TAG KEYS FROM src WHERE region = 'uswest' ORDER BY ASC, field1, field2 DESC LIMIT 10 ` ,
stmt : & influxql . ShowTagKeysStatement {
2014-12-20 04:36:52 +00:00
Source : & influxql . Measurement { Name : "src" } ,
2014-12-16 02:48:22 +00:00
Condition : & influxql . BinaryExpr {
2014-12-16 14:06:28 +00:00
Op : influxql . EQ ,
2014-12-16 02:48:22 +00:00
LHS : & influxql . VarRef { Val : "region" } ,
RHS : & influxql . StringLiteral { Val : "uswest" } ,
} ,
2015-01-12 19:47:22 +00:00
SortFields : [ ] * influxql . SortField {
2015-02-01 20:33:12 +00:00
{ Ascending : true } ,
{ Name : "field1" } ,
{ Name : "field2" } ,
2014-12-16 02:48:22 +00:00
} ,
Limit : 10 ,
} ,
} ,
2015-01-29 17:09:05 +00:00
// SHOW TAG VALUES FROM ... WITH KEY = ...
2014-12-16 02:48:22 +00:00
{
2015-01-29 17:09:05 +00:00
s : ` SHOW TAG VALUES FROM src WITH KEY = region WHERE region = 'uswest' ORDER BY ASC, field1, field2 DESC LIMIT 10 ` ,
2015-01-26 03:40:50 +00:00
stmt : & influxql . ShowTagValuesStatement {
2015-01-29 17:09:05 +00:00
Source : & influxql . Measurement { Name : "src" } ,
TagKeys : [ ] string { "region" } ,
2014-12-16 02:48:22 +00:00
Condition : & influxql . BinaryExpr {
2014-12-16 14:06:28 +00:00
Op : influxql . EQ ,
2014-12-16 02:48:22 +00:00
LHS : & influxql . VarRef { Val : "region" } ,
RHS : & influxql . StringLiteral { Val : "uswest" } ,
} ,
2015-01-12 19:47:22 +00:00
SortFields : [ ] * influxql . SortField {
2015-02-01 20:33:12 +00:00
{ Ascending : true } ,
{ Name : "field1" } ,
{ Name : "field2" } ,
2014-12-16 02:48:22 +00:00
} ,
Limit : 10 ,
} ,
} ,
2015-01-29 17:09:05 +00:00
// SHOW TAG VALUES FROM ... WITH KEY IN...
2015-01-28 10:02:36 +00:00
{
2015-01-29 17:09:05 +00:00
s : ` SHOW TAG VALUES FROM cpu WITH KEY IN (region, host) WHERE region = 'uswest' ` ,
2015-01-28 10:02:36 +00:00
stmt : & influxql . ShowTagValuesStatement {
2015-01-29 17:09:05 +00:00
Source : & influxql . Measurement { Name : "cpu" } ,
TagKeys : [ ] string { "region" , "host" } ,
2015-01-28 10:02:36 +00:00
Condition : & influxql . BinaryExpr {
2015-01-29 17:09:05 +00:00
Op : influxql . EQ ,
LHS : & influxql . VarRef { Val : "region" } ,
RHS : & influxql . StringLiteral { Val : "uswest" } ,
2015-01-28 10:02:36 +00:00
} ,
} ,
} ,
// SHOW TAG VALUES ... AND TAG KEY =
{
2015-01-29 17:09:05 +00:00
s : ` SHOW TAG VALUES FROM cpu WITH KEY IN (region,service,host)WHERE region = 'uswest' ` ,
2015-01-28 10:02:36 +00:00
stmt : & influxql . ShowTagValuesStatement {
2015-01-29 17:09:05 +00:00
Source : & influxql . Measurement { Name : "cpu" } ,
TagKeys : [ ] string { "region" , "service" , "host" } ,
2015-01-28 10:02:36 +00:00
Condition : & influxql . BinaryExpr {
2015-01-29 17:09:05 +00:00
Op : influxql . EQ ,
LHS : & influxql . VarRef { Val : "region" } ,
RHS : & influxql . StringLiteral { Val : "uswest" } ,
2015-01-28 10:02:36 +00:00
} ,
} ,
} ,
2015-01-29 17:09:05 +00:00
// SHOW TAG VALUES WITH KEY = ...
2015-01-28 10:02:36 +00:00
{
2015-01-29 17:09:05 +00:00
s : ` SHOW TAG VALUES WITH KEY = host WHERE region = 'uswest' ` ,
2015-01-28 10:02:36 +00:00
stmt : & influxql . ShowTagValuesStatement {
2015-01-29 17:09:05 +00:00
TagKeys : [ ] string { "host" } ,
2015-01-28 10:02:36 +00:00
Condition : & influxql . BinaryExpr {
2015-01-29 17:09:05 +00:00
Op : influxql . EQ ,
LHS : & influxql . VarRef { Val : "region" } ,
RHS : & influxql . StringLiteral { Val : "uswest" } ,
2015-01-28 10:02:36 +00:00
} ,
} ,
} ,
2015-02-26 20:40:30 +00:00
// SHOW TAG VALUES WITH KEY = "..."
{
s : ` SHOW TAG VALUES WITH KEY = "host" WHERE region = 'uswest' ` ,
stmt : & influxql . ShowTagValuesStatement {
TagKeys : [ ] string { ` "host" ` } ,
Condition : & influxql . BinaryExpr {
Op : influxql . EQ ,
LHS : & influxql . VarRef { Val : "region" } ,
RHS : & influxql . StringLiteral { Val : "uswest" } ,
} ,
} ,
} ,
2015-01-26 03:40:50 +00:00
// SHOW USERS
2015-01-14 16:53:17 +00:00
{
2015-01-26 03:40:50 +00:00
s : ` SHOW USERS ` ,
stmt : & influxql . ShowUsersStatement { } ,
2015-01-14 16:53:17 +00:00
} ,
2015-01-26 03:40:50 +00:00
// SHOW FIELD KEYS
2014-12-16 02:48:22 +00:00
{
2015-02-16 20:30:58 +00:00
s : ` SHOW FIELD KEYS FROM src ORDER BY ASC, field1, field2 DESC LIMIT 10 ` ,
2015-01-26 03:40:50 +00:00
stmt : & influxql . ShowFieldKeysStatement {
2014-12-20 04:36:52 +00:00
Source : & influxql . Measurement { Name : "src" } ,
2015-01-12 19:47:22 +00:00
SortFields : [ ] * influxql . SortField {
2015-02-01 20:33:12 +00:00
{ Ascending : true } ,
{ Name : "field1" } ,
{ Name : "field2" } ,
2014-12-16 02:48:22 +00:00
} ,
Limit : 10 ,
} ,
} ,
2014-11-22 23:33:21 +00:00
// DROP SERIES statement
{
2015-02-17 23:29:25 +00:00
s : ` DROP SERIES 1 ` ,
stmt : & influxql . DropSeriesStatement { SeriesID : 1 } ,
} ,
{
s : ` DROP SERIES FROM src ` ,
stmt : & influxql . DropSeriesStatement { Source : & influxql . Measurement { Name : "src" } } ,
} ,
2015-02-18 22:20:07 +00:00
{
s : ` DROP SERIES WHERE host = 'hosta.influxdb.org' ` ,
stmt : & influxql . DropSeriesStatement {
Condition : & influxql . BinaryExpr {
Op : influxql . EQ ,
LHS : & influxql . VarRef { Val : "host" } ,
RHS : & influxql . StringLiteral { Val : "hosta.influxdb.org" } ,
} ,
} ,
} ,
2015-02-17 23:29:25 +00:00
{
s : ` DROP SERIES FROM src WHERE host = 'hosta.influxdb.org' ` ,
stmt : & influxql . DropSeriesStatement {
Source : & influxql . Measurement { Name : "src" } ,
Condition : & influxql . BinaryExpr {
Op : influxql . EQ ,
LHS : & influxql . VarRef { Val : "host" } ,
RHS : & influxql . StringLiteral { Val : "hosta.influxdb.org" } ,
} ,
} ,
2014-11-22 23:33:21 +00:00
} ,
2015-01-26 03:40:50 +00:00
// SHOW CONTINUOUS QUERIES statement
2014-11-22 23:33:21 +00:00
{
2015-01-26 03:40:50 +00:00
s : ` SHOW CONTINUOUS QUERIES ` ,
stmt : & influxql . ShowContinuousQueriesStatement { } ,
2014-11-22 23:33:21 +00:00
} ,
2015-01-06 21:30:27 +00:00
// CREATE CONTINUOUS QUERY ... INTO <measurement>
2014-11-25 04:49:09 +00:00
{
2015-01-20 02:44:47 +00:00
s : ` CREATE CONTINUOUS QUERY myquery ON testdb BEGIN SELECT count() INTO measure1 FROM myseries GROUP BY time(5m) END ` ,
2014-11-25 04:49:09 +00:00
stmt : & influxql . CreateContinuousQueryStatement {
2015-01-09 22:50:33 +00:00
Name : "myquery" ,
Database : "testdb" ,
2014-11-25 04:49:09 +00:00
Source : & influxql . SelectStatement {
2015-02-01 20:33:12 +00:00
Fields : [ ] * influxql . Field { { Expr : & influxql . Call { Name : "count" } } } ,
2015-01-06 21:30:27 +00:00
Target : & influxql . Target { Measurement : "measure1" } ,
Source : & influxql . Measurement { Name : "myseries" } ,
2015-01-20 02:44:47 +00:00
Dimensions : [ ] * influxql . Dimension {
2015-02-16 20:30:58 +00:00
{
2015-01-20 02:44:47 +00:00
Expr : & influxql . Call {
Name : "time" ,
Args : [ ] influxql . Expr {
& influxql . DurationLiteral { Val : 5 * time . Minute } ,
} ,
} ,
} ,
} ,
2015-01-06 21:30:27 +00:00
} ,
} ,
} ,
// CREATE CONTINUOUS QUERY ... INTO <retention-policy>.<measurement>
{
2015-01-20 02:44:47 +00:00
s : ` CREATE CONTINUOUS QUERY myquery ON testdb BEGIN SELECT count() INTO "1h.policy1"."cpu.load" FROM myseries GROUP BY time(5m) END ` ,
2015-01-06 21:30:27 +00:00
stmt : & influxql . CreateContinuousQueryStatement {
2015-01-09 22:50:33 +00:00
Name : "myquery" ,
Database : "testdb" ,
2015-01-06 21:30:27 +00:00
Source : & influxql . SelectStatement {
2015-02-01 20:33:12 +00:00
Fields : [ ] * influxql . Field { { Expr : & influxql . Call { Name : "count" } } } ,
2015-01-06 21:30:27 +00:00
Target : & influxql . Target {
2015-01-19 20:01:32 +00:00
Measurement : ` "1h.policy1"."cpu.load" ` ,
2015-01-06 21:30:27 +00:00
} ,
2014-12-20 04:36:52 +00:00
Source : & influxql . Measurement { Name : "myseries" } ,
2015-01-20 02:44:47 +00:00
Dimensions : [ ] * influxql . Dimension {
2015-02-16 20:30:58 +00:00
{
2015-01-20 02:44:47 +00:00
Expr : & influxql . Call {
Name : "time" ,
Args : [ ] influxql . Expr {
& influxql . DurationLiteral { Val : 5 * time . Minute } ,
} ,
} ,
} ,
} ,
2014-11-25 04:49:09 +00:00
} ,
} ,
} ,
2015-02-25 02:01:03 +00:00
// CREATE CONTINUOUS QUERY for non-aggregate SELECT stmts
{
s : ` CREATE CONTINUOUS QUERY myquery ON testdb BEGIN SELECT value INTO "policy1"."value" FROM myseries END ` ,
stmt : & influxql . CreateContinuousQueryStatement {
Name : "myquery" ,
Database : "testdb" ,
Source : & influxql . SelectStatement {
Fields : [ ] * influxql . Field { { Expr : & influxql . Call { Name : "value" } } } ,
Target : & influxql . Target {
Measurement : ` "policy1"."value" ` ,
} ,
Source : & influxql . Measurement { Name : "myseries" } ,
} ,
} ,
} ,
// CREATE CONTINUOUS QUERY for non-aggregate SELECT stmts with multiple values
{
s : ` CREATE CONTINUOUS QUERY myquery ON testdb BEGIN SELECT transmit_rx, transmit_tx INTO "policy1"."network" FROM myseries END ` ,
stmt : & influxql . CreateContinuousQueryStatement {
Name : "myquery" ,
Database : "testdb" ,
Source : & influxql . SelectStatement {
Fields : [ ] * influxql . Field { { Expr : & influxql . Call { Name : "transmit_rx" } } ,
{ Expr : & influxql . Call { Name : "transmit_tx" } } } ,
Target : & influxql . Target {
Measurement : ` "policy1"."network" ` ,
} ,
Source : & influxql . Measurement { Name : "myseries" } ,
} ,
} ,
} ,
2014-12-31 13:47:21 +00:00
// CREATE DATABASE statement
{
2014-12-31 14:01:01 +00:00
s : ` CREATE DATABASE testdb ` ,
2014-12-31 13:47:21 +00:00
stmt : & influxql . CreateDatabaseStatement {
2015-01-25 22:51:51 +00:00
Name : "testdb" ,
2014-12-31 13:47:21 +00:00
} ,
} ,
2014-12-31 16:22:07 +00:00
// CREATE USER statement
{
2015-01-19 20:01:32 +00:00
s : ` CREATE USER testuser WITH PASSWORD 'pwd1337' ` ,
2014-12-31 16:22:07 +00:00
stmt : & influxql . CreateUserStatement {
Name : "testuser" ,
Password : "pwd1337" ,
} ,
} ,
2015-01-09 22:50:33 +00:00
// CREATE USER ... WITH ALL PRIVILEGES
{
2015-01-19 20:01:32 +00:00
s : ` CREATE USER testuser WITH PASSWORD 'pwd1337' WITH ALL PRIVILEGES ` ,
2015-01-09 22:50:33 +00:00
stmt : & influxql . CreateUserStatement {
2015-01-11 23:14:22 +00:00
Name : "testuser" ,
Password : "pwd1337" ,
2015-01-09 22:50:33 +00:00
Privilege : influxql . NewPrivilege ( influxql . AllPrivileges ) ,
} ,
} ,
2014-11-22 23:33:21 +00:00
// DROP CONTINUOUS QUERY statement
{
2014-11-25 00:58:21 +00:00
s : ` DROP CONTINUOUS QUERY myquery ` ,
stmt : & influxql . DropContinuousQueryStatement { Name : "myquery" } ,
2014-11-22 23:33:21 +00:00
} ,
2015-01-05 03:32:49 +00:00
// DROP DATABASE statement
{
2015-01-05 03:56:25 +00:00
s : ` DROP DATABASE testdb ` ,
2015-01-25 22:51:51 +00:00
stmt : & influxql . DropDatabaseStatement { Name : "testdb" } ,
2015-01-05 03:32:49 +00:00
} ,
2015-02-23 21:26:56 +00:00
// DROP MEASUREMENT statement
{
s : ` DROP MEASUREMENT cpu ` ,
stmt : & influxql . DropMeasurementStatement { Name : "cpu" } ,
} ,
2015-01-13 21:46:07 +00:00
// DROP RETENTION POLICY
{
s : ` DROP RETENTION POLICY "1h.cpu" ON mydb ` ,
stmt : & influxql . DropRetentionPolicyStatement {
2015-01-19 20:01:32 +00:00
Name : ` "1h.cpu" ` ,
Database : ` mydb ` ,
2015-01-13 21:46:07 +00:00
} ,
} ,
2015-01-05 03:56:25 +00:00
// DROP USER statement
{
s : ` DROP USER jdoe ` ,
stmt : & influxql . DropUserStatement { Name : "jdoe" } ,
} ,
2015-01-03 07:06:18 +00:00
// GRANT READ
2015-01-03 03:56:26 +00:00
{
s : ` GRANT READ ON testdb TO jdoe ` ,
stmt : & influxql . GrantStatement {
Privilege : influxql . ReadPrivilege ,
On : "testdb" ,
User : "jdoe" ,
} ,
} ,
2015-01-03 07:06:18 +00:00
// GRANT WRITE
2015-01-03 03:56:26 +00:00
{
s : ` GRANT WRITE ON testdb TO jdoe ` ,
stmt : & influxql . GrantStatement {
Privilege : influxql . WritePrivilege ,
On : "testdb" ,
User : "jdoe" ,
} ,
} ,
2015-01-03 07:06:18 +00:00
// GRANT ALL
2015-01-03 03:56:26 +00:00
{
s : ` GRANT ALL ON testdb TO jdoe ` ,
stmt : & influxql . GrantStatement {
Privilege : influxql . AllPrivileges ,
On : "testdb" ,
User : "jdoe" ,
} ,
} ,
2015-01-03 07:06:18 +00:00
// GRANT ALL PRIVILEGES
2015-01-03 03:56:26 +00:00
{
s : ` GRANT ALL PRIVILEGES ON testdb TO jdoe ` ,
stmt : & influxql . GrantStatement {
Privilege : influxql . AllPrivileges ,
On : "testdb" ,
User : "jdoe" ,
} ,
} ,
2015-01-03 07:06:18 +00:00
// GRANT cluster admin
{
s : ` GRANT ALL PRIVILEGES TO jdoe ` ,
stmt : & influxql . GrantStatement {
Privilege : influxql . AllPrivileges ,
User : "jdoe" ,
} ,
} ,
// REVOKE READ
{
s : ` REVOKE READ on testdb FROM jdoe ` ,
stmt : & influxql . RevokeStatement {
Privilege : influxql . ReadPrivilege ,
On : "testdb" ,
User : "jdoe" ,
} ,
} ,
// REVOKE WRITE
{
s : ` REVOKE WRITE ON testdb FROM jdoe ` ,
stmt : & influxql . RevokeStatement {
Privilege : influxql . WritePrivilege ,
On : "testdb" ,
User : "jdoe" ,
} ,
} ,
// REVOKE ALL
{
s : ` REVOKE ALL ON testdb FROM jdoe ` ,
stmt : & influxql . RevokeStatement {
Privilege : influxql . AllPrivileges ,
On : "testdb" ,
User : "jdoe" ,
} ,
} ,
// REVOKE ALL PRIVILEGES
{
s : ` REVOKE ALL PRIVILEGES ON testdb FROM jdoe ` ,
stmt : & influxql . RevokeStatement {
Privilege : influxql . AllPrivileges ,
On : "testdb" ,
User : "jdoe" ,
} ,
} ,
// REVOKE cluster admin
{
s : ` REVOKE ALL FROM jdoe ` ,
stmt : & influxql . RevokeStatement {
Privilege : influxql . AllPrivileges ,
User : "jdoe" ,
} ,
} ,
2015-01-05 02:50:56 +00:00
// CREATE RETENTION POLICY
{
s : ` CREATE RETENTION POLICY policy1 ON testdb DURATION 1h REPLICATION 2 ` ,
stmt : & influxql . CreateRetentionPolicyStatement {
Name : "policy1" ,
2015-01-09 22:50:33 +00:00
Database : "testdb" ,
2015-01-05 02:50:56 +00:00
Duration : time . Hour ,
Replication : 2 ,
} ,
} ,
2015-03-05 23:19:43 +00:00
// CREATE RETENTION POLICY with infinite retention
{
s : ` CREATE RETENTION POLICY policy1 ON testdb DURATION INF REPLICATION 2 ` ,
stmt : & influxql . CreateRetentionPolicyStatement {
Name : "policy1" ,
Database : "testdb" ,
Duration : 0 ,
Replication : 2 ,
} ,
} ,
2015-01-05 02:50:56 +00:00
// CREATE RETENTION POLICY ... DEFAULT
{
s : ` CREATE RETENTION POLICY policy1 ON testdb DURATION 2m REPLICATION 4 DEFAULT ` ,
stmt : & influxql . CreateRetentionPolicyStatement {
Name : "policy1" ,
2015-01-09 22:50:33 +00:00
Database : "testdb" ,
2015-01-05 02:50:56 +00:00
Duration : 2 * time . Minute ,
Replication : 4 ,
Default : true ,
} ,
} ,
2015-01-05 18:24:50 +00:00
// ALTER RETENTION POLICY
{
s : ` ALTER RETENTION POLICY policy1 ON testdb DURATION 1m REPLICATION 4 DEFAULT ` ,
stmt : newAlterRetentionPolicyStatement ( "policy1" , "testdb" , time . Minute , 4 , true ) ,
} ,
// ALTER RETENTION POLICY with options in reverse order
{
s : ` ALTER RETENTION POLICY policy1 ON testdb DEFAULT REPLICATION 4 DURATION 1m ` ,
stmt : newAlterRetentionPolicyStatement ( "policy1" , "testdb" , time . Minute , 4 , true ) ,
} ,
2015-03-05 23:19:43 +00:00
// ALTER RETENTION POLICY with infinite retention
{
s : ` ALTER RETENTION POLICY policy1 ON testdb DEFAULT REPLICATION 4 DURATION INF ` ,
stmt : newAlterRetentionPolicyStatement ( "policy1" , "testdb" , 0 , 4 , true ) ,
} ,
2015-01-05 18:24:50 +00:00
// ALTER RETENTION POLICY without optional DURATION
{
s : ` ALTER RETENTION POLICY policy1 ON testdb DEFAULT REPLICATION 4 ` ,
stmt : newAlterRetentionPolicyStatement ( "policy1" , "testdb" , - 1 , 4 , true ) ,
} ,
// ALTER RETENTION POLICY without optional REPLICATION
{
s : ` ALTER RETENTION POLICY policy1 ON testdb DEFAULT ` ,
stmt : newAlterRetentionPolicyStatement ( "policy1" , "testdb" , - 1 , - 1 , true ) ,
} ,
// ALTER RETENTION POLICY without optional DEFAULT
{
s : ` ALTER RETENTION POLICY policy1 ON testdb REPLICATION 4 ` ,
stmt : newAlterRetentionPolicyStatement ( "policy1" , "testdb" , - 1 , 4 , false ) ,
} ,
2014-11-22 04:12:48 +00:00
// Errors
{ s : ` ` , err : ` found EOF, expected SELECT at line 1, char 1 ` } ,
{ s : ` SELECT ` , err : ` found EOF, expected identifier, string, number, bool at line 1, char 8 ` } ,
2014-11-25 01:23:33 +00:00
{ s : ` blah blah ` , err : ` found blah, expected SELECT at line 1, char 1 ` } ,
2014-12-15 00:54:51 +00:00
{ s : ` SELECT field1 X ` , err : ` found X, expected FROM at line 1, char 15 ` } ,
2015-01-19 23:01:24 +00:00
{ s : ` SELECT field1 FROM "series" WHERE X +; ` , err : ` found ;, expected identifier, string, number, bool at line 1, char 38 ` } ,
2014-12-15 00:54:51 +00:00
{ s : ` SELECT field1 FROM myseries GROUP ` , err : ` found EOF, expected BY at line 1, char 35 ` } ,
{ s : ` SELECT field1 FROM myseries LIMIT ` , err : ` found EOF, expected number at line 1, char 35 ` } ,
2015-01-25 20:34:49 +00:00
{ s : ` SELECT field1 FROM myseries LIMIT 10.5 ` , err : ` fractional parts not allowed in LIMIT at line 1, char 35 ` } ,
2014-12-16 17:32:08 +00:00
{ s : ` SELECT field1 FROM myseries LIMIT 0 ` , err : ` LIMIT must be > 0 at line 1, char 35 ` } ,
2015-01-25 20:34:49 +00:00
{ s : ` SELECT field1 FROM myseries OFFSET ` , err : ` found EOF, expected number at line 1, char 36 ` } ,
{ s : ` SELECT field1 FROM myseries OFFSET 10.5 ` , err : ` fractional parts not allowed in OFFSET at line 1, char 36 ` } ,
{ s : ` SELECT field1 FROM myseries OFFSET 0 ` , err : ` OFFSET must be > 0 at line 1, char 36 ` } ,
2014-12-15 00:54:51 +00:00
{ s : ` SELECT field1 FROM myseries ORDER ` , err : ` found EOF, expected BY at line 1, char 35 ` } ,
{ s : ` SELECT field1 FROM myseries ORDER BY / ` , err : ` found /, expected identifier, ASC, or DESC at line 1, char 38 ` } ,
{ s : ` SELECT field1 FROM myseries ORDER BY 1 ` , err : ` found 1, expected identifier, ASC, or DESC at line 1, char 38 ` } ,
2015-01-19 23:01:24 +00:00
{ s : ` SELECT field1 AS ` , err : ` found EOF, expected identifier at line 1, char 18 ` } ,
{ s : ` SELECT field1 FROM 12 ` , err : ` found 12, expected identifier at line 1, char 20 ` } ,
2014-11-22 23:33:21 +00:00
{ s : ` SELECT 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 FROM myseries ` , err : ` unable to parse number at line 1, char 8 ` } ,
{ s : ` SELECT 10.5h FROM myseries ` , err : ` found h, expected FROM at line 1, char 12 ` } ,
{ s : ` DELETE ` , err : ` found EOF, expected FROM at line 1, char 8 ` } ,
2015-01-19 23:01:24 +00:00
{ s : ` DELETE FROM ` , err : ` found EOF, expected identifier at line 1, char 13 ` } ,
2014-11-22 23:33:21 +00:00
{ s : ` DELETE FROM myseries WHERE ` , err : ` found EOF, expected identifier, string, number, bool at line 1, char 28 ` } ,
2015-02-23 20:51:52 +00:00
{ s : ` DROP MEASUREMENT ` , err : ` found EOF, expected identifier at line 1, char 18 ` } ,
2015-02-17 23:29:25 +00:00
{ s : ` DROP SERIES ` , err : ` found EOF, expected number at line 1, char 13 ` } ,
{ s : ` DROP SERIES FROM ` , err : ` found EOF, expected identifier at line 1, char 18 ` } ,
2015-02-17 23:52:52 +00:00
{ s : ` DROP SERIES FROM src WHERE ` , err : ` found EOF, expected identifier, string, number, bool at line 1, char 28 ` } ,
2015-01-26 03:40:50 +00:00
{ s : ` SHOW CONTINUOUS ` , err : ` found EOF, expected QUERIES at line 1, char 17 ` } ,
{ s : ` SHOW RETENTION ` , err : ` found EOF, expected POLICIES at line 1, char 16 ` } ,
{ s : ` SHOW RETENTION POLICIES ` , err : ` found EOF, expected identifier at line 1, char 25 ` } ,
2015-02-10 01:06:18 +00:00
{ s : ` SHOW FOO ` , err : ` found FOO, expected CONTINUOUS, DATABASES, FIELD, MEASUREMENTS, RETENTION, SERIES, TAG, USERS at line 1, char 6 ` } ,
2014-11-22 23:33:21 +00:00
{ s : ` DROP CONTINUOUS ` , err : ` found EOF, expected QUERY at line 1, char 17 ` } ,
2015-01-19 23:01:24 +00:00
{ s : ` DROP CONTINUOUS QUERY ` , err : ` found EOF, expected identifier at line 1, char 23 ` } ,
2015-02-25 02:01:03 +00:00
{ s : ` CREATE CONTINUOUS ` , err : ` found EOF, expected QUERY at line 1, char 19 ` } ,
{ s : ` CREATE CONTINUOUS QUERY ` , err : ` found EOF, expected identifier at line 1, char 25 ` } ,
2015-02-23 20:51:52 +00:00
{ s : ` DROP FOO ` , err : ` found FOO, expected SERIES, CONTINUOUS, MEASUREMENT at line 1, char 6 ` } ,
2015-01-05 03:32:49 +00:00
{ s : ` DROP DATABASE ` , err : ` found EOF, expected identifier at line 1, char 15 ` } ,
2015-01-13 21:46:07 +00:00
{ s : ` DROP RETENTION ` , err : ` found EOF, expected POLICY at line 1, char 16 ` } ,
{ s : ` DROP RETENTION POLICY ` , err : ` found EOF, expected identifier at line 1, char 23 ` } ,
2015-01-19 20:01:32 +00:00
{ s : ` DROP RETENTION POLICY "1h.cpu" ` , err : ` found EOF, expected ON at line 1, char 32 ` } ,
2015-01-13 21:46:07 +00:00
{ s : ` DROP RETENTION POLICY "1h.cpu" ON ` , err : ` found EOF, expected identifier at line 1, char 35 ` } ,
2015-01-05 03:56:25 +00:00
{ s : ` DROP USER ` , err : ` found EOF, expected identifier at line 1, char 11 ` } ,
2014-12-31 16:22:07 +00:00
{ s : ` CREATE USER testuser ` , err : ` found EOF, expected WITH at line 1, char 22 ` } ,
2015-01-09 22:50:33 +00:00
{ s : ` CREATE USER testuser WITH ` , err : ` found EOF, expected PASSWORD at line 1, char 27 ` } ,
2015-01-19 20:01:32 +00:00
{ s : ` CREATE USER testuser WITH PASSWORD ` , err : ` found EOF, expected string at line 1, char 36 ` } ,
{ s : ` CREATE USER testuser WITH PASSWORD 'pwd' WITH ` , err : ` found EOF, expected ALL at line 1, char 47 ` } ,
{ s : ` CREATE USER testuser WITH PASSWORD 'pwd' WITH ALL ` , err : ` found EOF, expected PRIVILEGES at line 1, char 51 ` } ,
2015-01-03 03:56:26 +00:00
{ s : ` GRANT ` , err : ` found EOF, expected READ, WRITE, ALL [PRIVILEGES] at line 1, char 7 ` } ,
{ s : ` GRANT BOGUS ` , err : ` found BOGUS, expected READ, WRITE, ALL [PRIVILEGES] at line 1, char 7 ` } ,
{ s : ` GRANT READ ` , err : ` found EOF, expected ON at line 1, char 12 ` } ,
2015-01-03 07:06:18 +00:00
{ s : ` GRANT READ TO jdoe ` , err : ` found TO, expected ON at line 1, char 12 ` } ,
2015-01-19 23:01:24 +00:00
{ s : ` GRANT READ ON ` , err : ` found EOF, expected identifier at line 1, char 15 ` } ,
2015-01-03 03:56:26 +00:00
{ s : ` GRANT READ ON testdb ` , err : ` found EOF, expected TO at line 1, char 22 ` } ,
2015-01-19 23:01:24 +00:00
{ s : ` GRANT READ ON testdb TO ` , err : ` found EOF, expected identifier at line 1, char 25 ` } , { s : ` GRANT ` , err : ` found EOF, expected READ, WRITE, ALL [PRIVILEGES] at line 1, char 7 ` } ,
2015-01-03 07:06:18 +00:00
{ s : ` REVOKE BOGUS ` , err : ` found BOGUS, expected READ, WRITE, ALL [PRIVILEGES] at line 1, char 8 ` } ,
{ s : ` REVOKE READ ` , err : ` found EOF, expected ON at line 1, char 13 ` } ,
{ s : ` REVOKE READ TO jdoe ` , err : ` found TO, expected ON at line 1, char 13 ` } ,
2015-01-19 23:01:24 +00:00
{ s : ` REVOKE READ ON ` , err : ` found EOF, expected identifier at line 1, char 16 ` } ,
2015-01-03 07:06:18 +00:00
{ s : ` REVOKE READ ON testdb ` , err : ` found EOF, expected FROM at line 1, char 23 ` } ,
2015-01-19 23:01:24 +00:00
{ s : ` REVOKE READ ON testdb FROM ` , err : ` found EOF, expected identifier at line 1, char 28 ` } ,
2015-01-05 02:50:56 +00:00
{ s : ` CREATE RETENTION ` , err : ` found EOF, expected POLICY at line 1, char 18 ` } ,
{ s : ` CREATE RETENTION POLICY ` , err : ` found EOF, expected identifier at line 1, char 25 ` } ,
{ s : ` CREATE RETENTION POLICY policy1 ` , err : ` found EOF, expected ON at line 1, char 33 ` } ,
{ s : ` CREATE RETENTION POLICY policy1 ON ` , err : ` found EOF, expected identifier at line 1, char 36 ` } ,
{ s : ` CREATE RETENTION POLICY policy1 ON testdb ` , err : ` found EOF, expected DURATION at line 1, char 43 ` } ,
{ s : ` CREATE RETENTION POLICY policy1 ON testdb DURATION ` , err : ` found EOF, expected duration at line 1, char 52 ` } ,
{ s : ` CREATE RETENTION POLICY policy1 ON testdb DURATION bad ` , err : ` found bad, expected duration at line 1, char 52 ` } ,
{ s : ` CREATE RETENTION POLICY policy1 ON testdb DURATION 1h ` , err : ` found EOF, expected REPLICATION at line 1, char 54 ` } ,
{ s : ` CREATE RETENTION POLICY policy1 ON testdb DURATION 1h REPLICATION ` , err : ` found EOF, expected number at line 1, char 67 ` } ,
2015-01-05 18:24:50 +00:00
{ s : ` CREATE RETENTION POLICY policy1 ON testdb DURATION 1h REPLICATION 3.14 ` , err : ` number must be an integer at line 1, char 67 ` } ,
2015-01-06 18:47:21 +00:00
{ s : ` CREATE RETENTION POLICY policy1 ON testdb DURATION 1h REPLICATION 0 ` , err : ` invalid value 0: must be 1 <= n <= 2147483647 at line 1, char 67 ` } ,
2015-01-05 02:50:56 +00:00
{ s : ` CREATE RETENTION POLICY policy1 ON testdb DURATION 1h REPLICATION bad ` , err : ` found bad, expected number at line 1, char 67 ` } ,
2015-01-05 18:24:50 +00:00
{ s : ` ALTER ` , err : ` found EOF, expected RETENTION at line 1, char 7 ` } ,
{ s : ` ALTER RETENTION ` , err : ` found EOF, expected POLICY at line 1, char 17 ` } ,
{ s : ` ALTER RETENTION POLICY ` , err : ` found EOF, expected identifier at line 1, char 24 ` } ,
2015-02-25 02:01:03 +00:00
{ s : ` ALTER RETENTION POLICY policy1 ` , err : ` found EOF, expected ON at line 1, char 32 ` } , { s : ` ALTER RETENTION POLICY policy1 ON ` , err : ` found EOF, expected identifier at line 1, char 35 ` } ,
2015-01-05 18:24:50 +00:00
{ s : ` ALTER RETENTION POLICY policy1 ON testdb ` , err : ` found EOF, expected DURATION, RETENTION, DEFAULT at line 1, char 42 ` } ,
2014-11-22 04:12:48 +00:00
}
for i , tt := range tests {
stmt , err := influxql . NewParser ( strings . NewReader ( tt . s ) ) . ParseStatement ( )
2015-01-20 02:44:47 +00:00
2014-11-22 04:12:48 +00:00
if ! reflect . DeepEqual ( tt . err , errstring ( err ) ) {
t . Errorf ( "%d. %q: error mismatch:\n exp=%s\n got=%s\n\n" , i , tt . s , tt . err , err )
2015-02-25 02:01:03 +00:00
} else if st , ok := stmt . ( * influxql . CreateContinuousQueryStatement ) ; ok { // if it's a CQ, there is a non-exported field that gets memoized during parsing that needs to be set
if st != nil && st . Source != nil {
tt . stmt . ( * influxql . CreateContinuousQueryStatement ) . Source . GroupByInterval ( )
}
2014-11-22 04:12:48 +00:00
} else if tt . err == "" && ! reflect . DeepEqual ( tt . stmt , stmt ) {
2015-03-02 16:33:51 +00:00
t . Logf ( "exp=%s\ngot=%s\n" , mustMarshalJSON ( tt . stmt ) , mustMarshalJSON ( stmt ) )
2014-11-22 04:12:48 +00:00
t . Errorf ( "%d. %q\n\nstmt mismatch:\n\nexp=%#v\n\ngot=%#v\n\n" , i , tt . s , tt . stmt , stmt )
}
}
}
// Ensure the parser can parse expressions into an AST.
func TestParser_ParseExpr ( t * testing . T ) {
var tests = [ ] struct {
s string
expr influxql . Expr
err string
} {
2014-12-15 15:34:32 +00:00
// Primitives
2014-11-22 04:12:48 +00:00
{ s : ` 100 ` , expr : & influxql . NumberLiteral { Val : 100 } } ,
2015-01-19 20:01:32 +00:00
{ s : ` 'foo bar' ` , expr : & influxql . StringLiteral { Val : "foo bar" } } ,
2014-11-22 04:12:48 +00:00
{ s : ` true ` , expr : & influxql . BooleanLiteral { Val : true } } ,
{ s : ` false ` , expr : & influxql . BooleanLiteral { Val : false } } ,
{ s : ` my_ident ` , expr : & influxql . VarRef { Val : "my_ident" } } ,
2015-01-19 20:01:32 +00:00
{ s : ` '2000-01-01 00:00:00' ` , expr : & influxql . TimeLiteral { Val : mustParseTime ( "2000-01-01T00:00:00Z" ) } } ,
2015-02-05 22:51:36 +00:00
{ s : ` '2000-01-01 00:00:00.232' ` , expr : & influxql . TimeLiteral { Val : mustParseTime ( "2000-01-01T00:00:00.232Z" ) } } ,
2015-01-19 20:01:32 +00:00
{ s : ` '2000-01-32 00:00:00' ` , err : ` unable to parse datetime at line 1, char 1 ` } ,
{ s : ` '2000-01-01' ` , expr : & influxql . TimeLiteral { Val : mustParseTime ( "2000-01-01T00:00:00Z" ) } } ,
{ s : ` '2000-01-99' ` , err : ` unable to parse date at line 1, char 1 ` } ,
2014-11-22 04:12:48 +00:00
2014-12-15 15:34:32 +00:00
// Simple binary expression
2014-11-22 04:12:48 +00:00
{
s : ` 1 + 2 ` ,
expr : & influxql . BinaryExpr {
Op : influxql . ADD ,
LHS : & influxql . NumberLiteral { Val : 1 } ,
RHS : & influxql . NumberLiteral { Val : 2 } ,
} ,
} ,
2014-12-15 15:34:32 +00:00
// Binary expression with LHS precedence
2014-11-22 04:12:48 +00:00
{
s : ` 1 * 2 + 3 ` ,
expr : & influxql . BinaryExpr {
Op : influxql . ADD ,
LHS : & influxql . BinaryExpr {
Op : influxql . MUL ,
LHS : & influxql . NumberLiteral { Val : 1 } ,
RHS : & influxql . NumberLiteral { Val : 2 } ,
} ,
RHS : & influxql . NumberLiteral { Val : 3 } ,
} ,
} ,
2014-12-15 15:34:32 +00:00
// Binary expression with RHS precedence
2014-11-22 04:12:48 +00:00
{
s : ` 1 + 2 * 3 ` ,
expr : & influxql . BinaryExpr {
Op : influxql . ADD ,
LHS : & influxql . NumberLiteral { Val : 1 } ,
RHS : & influxql . BinaryExpr {
Op : influxql . MUL ,
LHS : & influxql . NumberLiteral { Val : 2 } ,
RHS : & influxql . NumberLiteral { Val : 3 } ,
} ,
} ,
} ,
2014-12-15 15:34:32 +00:00
// Binary expression with LHS paren group.
2014-11-25 06:12:32 +00:00
{
s : ` (1 + 2) * 3 ` ,
expr : & influxql . BinaryExpr {
Op : influxql . MUL ,
LHS : & influxql . ParenExpr {
Expr : & influxql . BinaryExpr {
Op : influxql . ADD ,
LHS : & influxql . NumberLiteral { Val : 1 } ,
RHS : & influxql . NumberLiteral { Val : 2 } ,
} ,
} ,
RHS : & influxql . NumberLiteral { Val : 3 } ,
} ,
} ,
2014-12-31 23:50:10 +00:00
// Binary expression with no precedence, tests left associativity.
{
s : ` 1 * 2 * 3 ` ,
expr : & influxql . BinaryExpr {
Op : influxql . MUL ,
LHS : & influxql . BinaryExpr {
Op : influxql . MUL ,
LHS : & influxql . NumberLiteral { Val : 1 } ,
RHS : & influxql . NumberLiteral { Val : 2 } ,
} ,
RHS : & influxql . NumberLiteral { Val : 3 } ,
} ,
} ,
2015-03-03 02:21:37 +00:00
// Binary expression with regex.
2015-02-13 18:25:48 +00:00
{
2015-03-03 02:21:37 +00:00
s : "region =~ /us.*/" ,
2015-02-13 18:25:48 +00:00
expr : & influxql . BinaryExpr {
Op : influxql . EQREGEX ,
LHS : & influxql . VarRef { Val : "region" } ,
RHS : & influxql . RegexLiteral { Val : regexp . MustCompile ( ` us.* ` ) } ,
} ,
} ,
2014-12-15 15:34:32 +00:00
// Complex binary expression.
2014-11-22 04:12:48 +00:00
{
s : ` value + 3 < 30 AND 1 + 2 OR true ` ,
expr : & influxql . BinaryExpr {
Op : influxql . OR ,
LHS : & influxql . BinaryExpr {
Op : influxql . AND ,
LHS : & influxql . BinaryExpr {
Op : influxql . LT ,
LHS : & influxql . BinaryExpr {
Op : influxql . ADD ,
LHS : & influxql . VarRef { Val : "value" } ,
RHS : & influxql . NumberLiteral { Val : 3 } ,
} ,
RHS : & influxql . NumberLiteral { Val : 30 } ,
} ,
RHS : & influxql . BinaryExpr {
Op : influxql . ADD ,
LHS : & influxql . NumberLiteral { Val : 1 } ,
RHS : & influxql . NumberLiteral { Val : 2 } ,
} ,
} ,
RHS : & influxql . BooleanLiteral { Val : true } ,
} ,
} ,
2014-11-25 03:43:23 +00:00
2014-12-15 15:34:32 +00:00
// Function call (empty)
2014-11-25 03:43:23 +00:00
{
s : ` my_func() ` ,
expr : & influxql . Call {
Name : "my_func" ,
} ,
} ,
2014-12-15 15:34:32 +00:00
// Function call (multi-arg)
2014-11-25 03:43:23 +00:00
{
s : ` my_func(1, 2 + 3) ` ,
expr : & influxql . Call {
Name : "my_func" ,
Args : [ ] influxql . Expr {
& influxql . NumberLiteral { Val : 1 } ,
& influxql . BinaryExpr {
Op : influxql . ADD ,
LHS : & influxql . NumberLiteral { Val : 2 } ,
RHS : & influxql . NumberLiteral { Val : 3 } ,
} ,
} ,
} ,
} ,
2014-11-22 04:12:48 +00:00
}
for i , tt := range tests {
expr , err := influxql . NewParser ( strings . NewReader ( tt . s ) ) . ParseExpr ( )
if ! reflect . DeepEqual ( tt . err , errstring ( err ) ) {
t . Errorf ( "%d. %q: error mismatch:\n exp=%s\n got=%s\n\n" , i , tt . s , tt . err , err )
} else if tt . err == "" && ! reflect . DeepEqual ( tt . expr , expr ) {
t . Errorf ( "%d. %q\n\nexpr mismatch:\n\nexp=%#v\n\ngot=%#v\n\n" , i , tt . s , tt . expr , expr )
}
}
}
// Ensure a time duration can be parsed.
func TestParseDuration ( t * testing . T ) {
var tests = [ ] struct {
s string
d time . Duration
err string
} {
{ s : ` 3 ` , d : 3 * time . Microsecond } ,
{ s : ` 1000 ` , d : 1000 * time . Microsecond } ,
{ s : ` 10u ` , d : 10 * time . Microsecond } ,
2014-11-25 06:43:23 +00:00
{ s : ` 10µ ` , d : 10 * time . Microsecond } ,
2014-11-22 04:12:48 +00:00
{ s : ` 15ms ` , d : 15 * time . Millisecond } ,
{ s : ` 100s ` , d : 100 * time . Second } ,
{ s : ` 2m ` , d : 2 * time . Minute } ,
{ s : ` 2h ` , d : 2 * time . Hour } ,
{ s : ` 2d ` , d : 2 * 24 * time . Hour } ,
{ s : ` 2w ` , d : 2 * 7 * 24 * time . Hour } ,
{ s : ` ` , err : "invalid duration" } ,
{ s : ` w ` , err : "invalid duration" } ,
{ s : ` 1.2w ` , err : "invalid duration" } ,
{ s : ` 10x ` , err : "invalid duration" } ,
}
for i , tt := range tests {
d , err := influxql . ParseDuration ( tt . s )
if ! reflect . DeepEqual ( tt . err , errstring ( err ) ) {
t . Errorf ( "%d. %q: error mismatch:\n exp=%s\n got=%s\n\n" , i , tt . s , tt . err , err )
} else if tt . d != d {
t . Errorf ( "%d. %q\n\nduration mismatch:\n\nexp=%#v\n\ngot=%#v\n\n" , i , tt . s , tt . d , d )
}
}
}
2014-12-06 18:17:58 +00:00
// Ensure a time duration can be formatted.
func TestFormatDuration ( t * testing . T ) {
var tests = [ ] struct {
d time . Duration
s string
} {
{ d : 3 * time . Microsecond , s : ` 3 ` } ,
{ d : 1001 * time . Microsecond , s : ` 1001 ` } ,
{ d : 15 * time . Millisecond , s : ` 15ms ` } ,
{ d : 100 * time . Second , s : ` 100s ` } ,
{ d : 2 * time . Minute , s : ` 2m ` } ,
{ d : 2 * time . Hour , s : ` 2h ` } ,
{ d : 2 * 24 * time . Hour , s : ` 2d ` } ,
{ d : 2 * 7 * 24 * time . Hour , s : ` 2w ` } ,
}
for i , tt := range tests {
s := influxql . FormatDuration ( tt . d )
if tt . s != s {
t . Errorf ( "%d. %v: mismatch: %s != %s" , i , tt . d , tt . s , s )
}
}
}
// Ensure a string can be quoted.
func TestQuote ( t * testing . T ) {
for i , tt := range [ ] struct {
in string
out string
} {
2015-01-19 20:01:32 +00:00
{ ` ` , ` '' ` } ,
{ ` foo ` , ` 'foo' ` } ,
{ "foo\nbar" , ` 'foo\nbar' ` } ,
{ ` foo bar\\ ` , ` 'foo bar\\\\' ` } ,
{ ` 'foo' ` , ` '\'foo\'' ` } ,
2014-12-06 18:17:58 +00:00
} {
2015-01-19 20:01:32 +00:00
if out := influxql . QuoteString ( tt . in ) ; tt . out != out {
2014-12-06 18:17:58 +00:00
t . Errorf ( "%d. %s: mismatch: %s != %s" , i , tt . in , tt . out , out )
}
}
}
2015-01-18 21:45:22 +00:00
// Ensure an identifier's segments can be quoted.
2014-12-06 18:17:58 +00:00
func TestQuoteIdent ( t * testing . T ) {
for i , tt := range [ ] struct {
2015-01-18 21:45:22 +00:00
ident [ ] string
2014-12-06 18:17:58 +00:00
s string
} {
2015-01-18 21:45:22 +00:00
{ [ ] string { ` ` } , ` "" ` } ,
{ [ ] string { ` foo ` , ` bar ` } , ` "foo"."bar" ` } ,
{ [ ] string { ` foo bar ` , ` baz ` } , ` "foo bar"."baz" ` } ,
{ [ ] string { ` foo.bar ` , ` baz ` } , ` "foo.bar"."baz" ` } ,
2014-12-06 18:17:58 +00:00
} {
if s := influxql . QuoteIdent ( tt . ident ) ; tt . s != s {
t . Errorf ( "%d. %s: mismatch: %s != %s" , i , tt . ident , tt . s , s )
}
}
}
2015-02-17 23:29:25 +00:00
// Ensure DropSeriesStatement can convert to a string
func TestDropSeriesStatement_String ( t * testing . T ) {
var tests = [ ] struct {
s string
stmt influxql . Statement
} {
{
s : ` DROP SERIES 1 ` ,
stmt : & influxql . DropSeriesStatement { SeriesID : 1 } ,
} ,
{
s : ` DROP SERIES FROM src ` ,
stmt : & influxql . DropSeriesStatement { Source : & influxql . Measurement { Name : "src" } } ,
} ,
{
s : ` DROP SERIES FROM src WHERE host = 'hosta.influxdb.org' ` ,
stmt : & influxql . DropSeriesStatement {
Source : & influxql . Measurement { Name : "src" } ,
Condition : & influxql . BinaryExpr {
Op : influxql . EQ ,
LHS : & influxql . VarRef { Val : "host" } ,
RHS : & influxql . StringLiteral { Val : "hosta.influxdb.org" } ,
} ,
} ,
} ,
2015-02-18 22:20:07 +00:00
{
s : ` DROP SERIES FROM src WHERE host = 'hosta.influxdb.org' ` ,
stmt : & influxql . DropSeriesStatement {
Source : & influxql . Measurement { Name : "src" } ,
Condition : & influxql . BinaryExpr {
Op : influxql . EQ ,
LHS : & influxql . VarRef { Val : "host" } ,
RHS : & influxql . StringLiteral { Val : "hosta.influxdb.org" } ,
} ,
} ,
} ,
{
s : ` DROP SERIES WHERE host = 'hosta.influxdb.org' ` ,
stmt : & influxql . DropSeriesStatement {
Condition : & influxql . BinaryExpr {
Op : influxql . EQ ,
LHS : & influxql . VarRef { Val : "host" } ,
RHS : & influxql . StringLiteral { Val : "hosta.influxdb.org" } ,
} ,
} ,
} ,
2015-02-17 23:29:25 +00:00
}
for _ , test := range tests {
s := test . stmt . String ( )
if s != test . s {
t . Errorf ( "error rendering string. expected %s, actual: %s" , test . s , s )
}
}
}
2014-11-25 00:58:21 +00:00
func BenchmarkParserParseStatement ( b * testing . B ) {
b . ReportAllocs ( )
s := ` SELECT field FROM "series" WHERE value > 10 `
for i := 0 ; i < b . N ; i ++ {
if stmt , err := influxql . NewParser ( strings . NewReader ( s ) ) . ParseStatement ( ) ; err != nil {
b . Fatalf ( "unexpected error: %s" , err )
} else if stmt == nil {
2015-01-11 23:14:22 +00:00
b . Fatalf ( "expected statement: %s" , stmt )
2014-11-25 00:58:21 +00:00
}
}
b . SetBytes ( int64 ( len ( s ) ) )
}
2014-12-08 05:08:39 +00:00
// MustParseSelectStatement parses a select statement. Panic on error.
func MustParseSelectStatement ( s string ) * influxql . SelectStatement {
stmt , err := influxql . NewParser ( strings . NewReader ( s ) ) . ParseStatement ( )
if err != nil {
panic ( err . Error ( ) )
}
return stmt . ( * influxql . SelectStatement )
}
2014-12-11 16:58:33 +00:00
// MustParseExpr parses an expression. Panic on error.
func MustParseExpr ( s string ) influxql . Expr {
expr , err := influxql . NewParser ( strings . NewReader ( s ) ) . ParseExpr ( )
if err != nil {
panic ( err . Error ( ) )
}
return expr
}
2014-11-22 04:12:48 +00:00
// errstring converts an error to its string representation.
func errstring ( err error ) string {
if err != nil {
return err . Error ( )
}
return ""
}
2015-01-05 18:24:50 +00:00
// newAlterRetentionPolicyStatement creates an initialized AlterRetentionPolicyStatement.
func newAlterRetentionPolicyStatement ( name string , DB string , d time . Duration , replication int , dfault bool ) * influxql . AlterRetentionPolicyStatement {
stmt := & influxql . AlterRetentionPolicyStatement {
2015-01-09 22:50:33 +00:00
Name : name ,
Database : DB ,
Default : dfault ,
2015-01-05 18:24:50 +00:00
}
if d > - 1 {
stmt . Duration = & d
}
if replication > - 1 {
stmt . Replication = & replication
}
return stmt
}
2015-03-08 00:30:42 +00:00
// mustMarshalJSON encodes a value to JSON.
func mustMarshalJSON ( v interface { } ) [ ] byte {
b , err := json . Marshal ( v )
if err != nil {
panic ( "marshal json: " + err . Error ( ) )
}
return b
}