Update parser and AST for explain statement

pull/8751/head
Jonathan A. Sternberg 2017-08-17 16:25:38 -05:00
parent 5dbcd1b06f
commit 5593eecda6
8 changed files with 117 additions and 17 deletions

View File

@ -134,6 +134,8 @@ func (e *StatementExecutor) ExecuteStatement(stmt influxql.Statement, ctx query.
messages = append(messages, query.ReadOnlyWarning(stmt.String()))
}
err = e.executeDropUserStatement(stmt)
case *influxql.ExplainStatement:
rows, err = e.executeExplainStatement(stmt, &ctx)
case *influxql.GrantStatement:
if ctx.ReadOnly {
messages = append(messages, query.ReadOnlyWarning(stmt.String()))
@ -398,6 +400,10 @@ func (e *StatementExecutor) executeDropUserStatement(q *influxql.DropUserStateme
return e.MetaClient.DropUser(q.Name)
}
func (e *StatementExecutor) executeExplainStatement(q *influxql.ExplainStatement, ctx *query.ExecutionContext) (models.Rows, error) {
return nil, errors.New("unimplemented")
}
func (e *StatementExecutor) executeGrantStatement(stmt *influxql.GrantStatement) error {
return e.MetaClient.SetPrivilege(stmt.User, stmt.On, stmt.Privilege)
}

View File

@ -113,19 +113,19 @@ _cpu_stats
## Keywords
```
ALL ALTER ANY AS ASC BEGIN
BY CREATE CONTINUOUS DATABASE DATABASES DEFAULT
DELETE DESC DESTINATIONS DIAGNOSTICS DISTINCT DROP
DURATION END EVERY EXPLAIN FIELD FOR
FROM GRANT GRANTS GROUP GROUPS IN
INF INSERT INTO KEY KEYS KILL
LIMIT SHOW MEASUREMENT MEASUREMENTS NAME OFFSET
ON ORDER PASSWORD POLICY POLICIES PRIVILEGES
QUERIES QUERY READ REPLICATION RESAMPLE RETENTION
REVOKE SELECT SERIES SET SHARD SHARDS
SLIMIT SOFFSET STATS SUBSCRIPTION SUBSCRIPTIONS TAG
TO USER USERS VALUES WHERE WITH
WRITE
ALL ALTER ANALYZE ANY AS ASC
BEGIN BY CREATE CONTINUOUS DATABASE DATABASES
DEFAULT DELETE DESC DESTINATIONS DIAGNOSTICS DISTINCT
DROP DURATION END EVERY EXPLAIN FIELD
FOR FROM GRANT GRANTS GROUP GROUPS
IN INF INSERT INTO KEY KEYS
KILL LIMIT SHOW MEASUREMENT MEASUREMENTS NAME
OFFSET ON ORDER PASSWORD POLICY POLICIES
PRIVILEGES QUERIES QUERY READ REPLICATION RESAMPLE
RETENTION REVOKE SELECT SERIES SET SHARD
SHARDS SLIMIT SOFFSET STATS SUBSCRIPTION SUBSCRIPTIONS
TAG TO USER USERS VALUES WHERE
WITH WRITE
```
## Literals
@ -229,6 +229,7 @@ statement = alter_retention_policy_stmt |
drop_shard_stmt |
drop_subscription_stmt |
drop_user_stmt |
explain_stmt |
grant_stmt |
kill_query_statement |
show_continuous_queries_stmt |
@ -526,6 +527,14 @@ drop_user_stmt = "DROP USER" user_name .
DROP USER "jdoe"
```
### EXPLAIN
> **NOTE:** This functionality is unimplemented.
```
explain_stmt = "EXPLAIN" [ "ANALYZE" ] select_stmt .
```
### GRANT
> **NOTE:** Users can be granted privileges on databases that do not exist.

View File

@ -142,6 +142,7 @@ func (*DropSeriesStatement) node() {}
func (*DropShardStatement) node() {}
func (*DropSubscriptionStatement) node() {}
func (*DropUserStatement) node() {}
func (*ExplainStatement) node() {}
func (*GrantStatement) node() {}
func (*GrantAdminStatement) node() {}
func (*KillQueryStatement) node() {}
@ -266,6 +267,7 @@ func (*DropRetentionPolicyStatement) stmt() {}
func (*DropSeriesStatement) stmt() {}
func (*DropSubscriptionStatement) stmt() {}
func (*DropUserStatement) stmt() {}
func (*ExplainStatement) stmt() {}
func (*GrantStatement) stmt() {}
func (*GrantAdminStatement) stmt() {}
func (*KillQueryStatement) stmt() {}
@ -1863,6 +1865,29 @@ func (t *Target) String() string {
return buf.String()
}
// ExplainStatement represents a command for explaining a select statement.
type ExplainStatement struct {
Statement *SelectStatement
Analyze bool
}
// String returns a string representation of the explain statement.
func (e *ExplainStatement) String() string {
var buf bytes.Buffer
buf.WriteString("EXPLAIN ")
if e.Analyze {
buf.WriteString("ANALYZE ")
}
buf.WriteString(e.Statement.String())
return buf.String()
}
// RequiredPrivileges returns the privilege required to execute a ExplainStatement.
func (e *ExplainStatement) RequiredPrivileges() (ExecutionPrivileges, error) {
return e.Statement.RequiredPrivileges()
}
// DeleteStatement represents a command for deleting data from the database.
type DeleteStatement struct {
// Data source that values are removed from.

View File

@ -1499,6 +1499,7 @@ func Test_EnforceHasDefaultDatabase(t *testing.T) {
"DropSeriesStatement",
"DropShardStatement",
"DropUserStatement",
"ExplainStatement",
"GrantAdminStatement",
"KillQueryStatement",
"RevokeAdminStatement",

View File

@ -1,6 +1,8 @@
package influxql
import "fmt"
import (
"fmt"
)
var Language = &ParseTree{}
@ -210,6 +212,9 @@ func init() {
return p.parseDropUserStatement()
})
})
Language.Handle(EXPLAIN, func(p *Parser) (Statement, error) {
return p.parseExplainStatement()
})
Language.Handle(GRANT, func(p *Parser) (Statement, error) {
return p.parseGrantStatement()
})

View File

@ -1884,6 +1884,29 @@ func (p *Parser) parseDropUserStatement() (*DropUserStatement, error) {
return stmt, nil
}
// parseExplainStatement parses a string and return an ExplainStatement.
// This function assumes the EXPLAIN token has already been consumed.
func (p *Parser) parseExplainStatement() (*ExplainStatement, error) {
stmt := &ExplainStatement{}
if tok, _, _ := p.ScanIgnoreWhitespace(); tok == ANALYZE {
stmt.Analyze = true
} else {
p.Unscan()
}
if tok, pos, lit := p.ScanIgnoreWhitespace(); tok != SELECT {
return nil, newParseError(tokstr(tok, lit), []string{"SELECT"}, pos)
}
s, err := p.parseSelectStatement(targetNotRequired)
if err != nil {
return nil, err
}
stmt.Statement = s
return stmt, nil
}
// parseShowShardGroupsStatement parses a string for "SHOW SHARD GROUPS" statement.
// This function assumes the "SHOW SHARD GROUPS" tokens have already been consumed.
func (p *Parser) parseShowShardGroupsStatement() (*ShowShardGroupsStatement, error) {

View File

@ -1437,6 +1437,35 @@ func TestParser_ParseStatement(t *testing.T) {
},
},
// EXPLAIN ...
{
s: `EXPLAIN SELECT * FROM cpu`,
stmt: &influxql.ExplainStatement{
Statement: &influxql.SelectStatement{
IsRawQuery: true,
Fields: []*influxql.Field{
{Expr: &influxql.Wildcard{}},
},
Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
},
},
},
// EXPLAIN ANALYZE ...
{
s: `EXPLAIN ANALYZE SELECT * FROM cpu`,
stmt: &influxql.ExplainStatement{
Statement: &influxql.SelectStatement{
IsRawQuery: true,
Fields: []*influxql.Field{
{Expr: &influxql.Wildcard{}},
},
Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
},
Analyze: true,
},
},
// See issues https://github.com/influxdata/influxdb/issues/1647
// and https://github.com/influxdata/influxdb/issues/4404
// DELETE statement
@ -2793,9 +2822,9 @@ func TestParser_ParseStatement(t *testing.T) {
},
// Errors
{s: ``, err: `found EOF, expected SELECT, DELETE, SHOW, CREATE, DROP, GRANT, REVOKE, ALTER, SET, KILL at line 1, char 1`},
{s: ``, err: `found EOF, expected SELECT, DELETE, SHOW, CREATE, DROP, EXPLAIN, GRANT, REVOKE, ALTER, SET, KILL at line 1, char 1`},
{s: `SELECT`, err: `found EOF, expected identifier, string, number, bool at line 1, char 8`},
{s: `blah blah`, err: `found blah, expected SELECT, DELETE, SHOW, CREATE, DROP, GRANT, REVOKE, ALTER, SET, KILL at line 1, char 1`},
{s: `blah blah`, err: `found blah, expected SELECT, DELETE, SHOW, CREATE, DROP, EXPLAIN, GRANT, REVOKE, ALTER, SET, KILL at line 1, char 1`},
{s: `SELECT field1 X`, err: `found X, expected FROM at line 1, char 15`},
{s: `SELECT field1 FROM "series" WHERE X +;`, err: `found ;, expected identifier, string, number, bool at line 1, char 38`},
{s: `SELECT field1 FROM myseries GROUP`, err: `found EOF, expected BY at line 1, char 35`},
@ -2981,7 +3010,7 @@ func TestParser_ParseStatement(t *testing.T) {
{s: `SET PASSWORD FOR dejan`, err: `found EOF, expected = at line 1, char 24`},
{s: `SET PASSWORD FOR dejan =`, err: `found EOF, expected string at line 1, char 25`},
{s: `SET PASSWORD FOR dejan = bla`, err: `found bla, expected string at line 1, char 26`},
{s: `$SHOW$DATABASES`, err: `found $SHOW, expected SELECT, DELETE, SHOW, CREATE, DROP, GRANT, REVOKE, ALTER, SET, KILL at line 1, char 1`},
{s: `$SHOW$DATABASES`, err: `found $SHOW, expected SELECT, DELETE, SHOW, CREATE, DROP, EXPLAIN, GRANT, REVOKE, ALTER, SET, KILL at line 1, char 1`},
{s: `SELECT * FROM cpu WHERE "tagkey" = $$`, err: `empty bound parameter`},
}

View File

@ -67,6 +67,7 @@ const (
// ALL and the following are InfluxQL Keywords
ALL
ALTER
ANALYZE
ANY
AS
ASC
@ -188,6 +189,7 @@ var tokens = [...]string{
ALL: "ALL",
ALTER: "ALTER",
ANALYZE: "ANALYZE",
ANY: "ANY",
AS: "AS",
ASC: "ASC",