Update parser and AST for explain statement
parent
5dbcd1b06f
commit
5593eecda6
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -1499,6 +1499,7 @@ func Test_EnforceHasDefaultDatabase(t *testing.T) {
|
|||
"DropSeriesStatement",
|
||||
"DropShardStatement",
|
||||
"DropUserStatement",
|
||||
"ExplainStatement",
|
||||
"GrantAdminStatement",
|
||||
"KillQueryStatement",
|
||||
"RevokeAdminStatement",
|
||||
|
|
|
@ -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()
|
||||
})
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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`},
|
||||
}
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in New Issue