influxql: add LIST USERS statement

pull/1324/head
David Norton 2015-01-14 11:53:17 -05:00
parent fd8e8a108d
commit 9e3ca7b569
7 changed files with 67 additions and 22 deletions

View File

@ -108,6 +108,9 @@ LIST FIELD KEYS FROM cpu
-- but you can't do this -- but you can't do this
LIST FIELD VALUES LIST FIELD VALUES
-- we don't index field values, so this query should be invalid. -- we don't index field values, so this query should be invalid.
-- list all users
LIST USERS
``` ```
Note that `FROM` and `WHERE` are optional clauses in all of the list series queries. Note that `FROM` and `WHERE` are optional clauses in all of the list series queries.

View File

@ -123,6 +123,7 @@ statement = alter_retention_policy_stmt |
list_series_stmt | list_series_stmt |
list_tag_key_stmt | list_tag_key_stmt |
list_tag_value_stmt | list_tag_value_stmt |
list_users_stmt |
revoke_stmt | revoke_stmt |
select_stmt . select_stmt .
``` ```
@ -307,6 +308,19 @@ list_retention_policies = "LIST RETENTION POLICIES" db_name .
LIST RETENTION POLICIES mydb; LIST RETENTION POLICIES mydb;
``` ```
### LIST USERS
```
list_users_stmt = "LIST USERES" .
```
#### Example:
```sql
-- list all users
LIST USERS;
```
## Clauses ## Clauses
``` ```

View File

@ -68,6 +68,7 @@ func (_ *ListMeasurementsStatement) node() {}
func (_ *ListSeriesStatement) node() {} func (_ *ListSeriesStatement) node() {}
func (_ *ListTagKeysStatement) node() {} func (_ *ListTagKeysStatement) node() {}
func (_ *ListTagValuesStatement) node() {} func (_ *ListTagValuesStatement) node() {}
func (_ *ListUsersStatement) node() {}
func (_ *RevokeStatement) node() {} func (_ *RevokeStatement) node() {}
func (_ *SelectStatement) node() {} func (_ *SelectStatement) node() {}
@ -140,6 +141,7 @@ func (_ *ListRetentionPoliciesStatement) stmt() {}
func (_ *ListSeriesStatement) stmt() {} func (_ *ListSeriesStatement) stmt() {}
func (_ *ListTagKeysStatement) stmt() {} func (_ *ListTagKeysStatement) stmt() {}
func (_ *ListTagValuesStatement) stmt() {} func (_ *ListTagValuesStatement) stmt() {}
func (_ *ListUsersStatement) stmt() {}
func (_ *RevokeStatement) stmt() {} func (_ *RevokeStatement) stmt() {}
func (_ *SelectStatement) stmt() {} func (_ *SelectStatement) stmt() {}
@ -897,6 +899,14 @@ func (s *ListTagValuesStatement) String() string {
return buf.String() return buf.String()
} }
// ListUsersStatement represents a command for listing users.
type ListUsersStatement struct{}
// String retuns a string representation of the ListUsersStatement.
func (s *ListUsersStatement) String() string {
return "LIST USERS"
}
// ListFieldKeyStatement represents a command for listing field keys. // ListFieldKeyStatement represents a command for listing field keys.
type ListFieldKeysStatement struct { type ListFieldKeysStatement struct {
// Data source that fields are extracted from. // Data source that fields are extracted from.

View File

@ -89,36 +89,39 @@ func (p *Parser) ParseStatement() (Statement, error) {
// This function assumes the LIST token has already been consumed. // This function assumes the LIST token has already been consumed.
func (p *Parser) parseListStatement() (Statement, error) { func (p *Parser) parseListStatement() (Statement, error) {
tok, pos, lit := p.scanIgnoreWhitespace() tok, pos, lit := p.scanIgnoreWhitespace()
if tok == SERIES { switch tok {
return p.parseListSeriesStatement() case CONTINUOUS:
} else if tok == CONTINUOUS {
return p.parseListContinuousQueriesStatement() return p.parseListContinuousQueriesStatement()
} else if tok == DATABASES { case DATABASES:
return p.parseListDatabasesStatement() return p.parseListDatabasesStatement()
} else if tok == MEASUREMENTS { case FIELD:
return p.parseListMeasurementsStatement() tok, pos, lit := p.scanIgnoreWhitespace()
} else if tok == TAG { if tok == KEYS {
if tok, pos, lit := p.scanIgnoreWhitespace(); tok == KEYS {
return p.parseListTagKeysStatement()
} else if tok == VALUES {
return p.parseListTagValuesStatement()
} else {
return nil, newParseError(tokstr(tok, lit), []string{"KEYS", "VALUES"}, pos)
}
} else if tok == FIELD {
if tok, pos, lit := p.scanIgnoreWhitespace(); tok == KEYS {
return p.parseListFieldKeysStatement() return p.parseListFieldKeysStatement()
} else if tok == VALUES { } else if tok == VALUES {
return p.parseListFieldValuesStatement() return p.parseListFieldValuesStatement()
} else {
return nil, newParseError(tokstr(tok, lit), []string{"KEYS", "VALUES"}, pos)
} }
} else if tok == RETENTION { return nil, newParseError(tokstr(tok, lit), []string{"KEYS", "VALUES"}, pos)
if tok, pos, lit := p.scanIgnoreWhitespace(); tok == POLICIES { case MEASUREMENTS:
return p.parseListMeasurementsStatement()
case RETENTION:
tok, pos, lit := p.scanIgnoreWhitespace()
if tok == POLICIES {
return p.parseListRetentionPoliciesStatement() return p.parseListRetentionPoliciesStatement()
} else {
return nil, newParseError(tokstr(tok, lit), []string{"POLICIES"}, pos)
} }
return nil, newParseError(tokstr(tok, lit), []string{"POLICIES"}, pos)
case SERIES:
return p.parseListSeriesStatement()
case TAG:
tok, pos, lit := p.scanIgnoreWhitespace()
if tok == KEYS {
return p.parseListTagKeysStatement()
} else if tok == VALUES {
return p.parseListTagValuesStatement()
}
return nil, newParseError(tokstr(tok, lit), []string{"KEYS", "VALUES"}, pos)
case USERS:
return p.parseListUsersStatement()
} }
return nil, newParseError(tokstr(tok, lit), []string{"SERIES", "CONTINUOUS", "MEASUREMENTS", "TAG", "FIELD", "RETENTION"}, pos) return nil, newParseError(tokstr(tok, lit), []string{"SERIES", "CONTINUOUS", "MEASUREMENTS", "TAG", "FIELD", "RETENTION"}, pos)
@ -747,6 +750,12 @@ func (p *Parser) parseListTagValuesStatement() (*ListTagValuesStatement, error)
return stmt, nil return stmt, nil
} }
// parseListUsersStatement parses a string and returns a ListUsersStatement.
// This function assumes the "LIST USERS" tokens have been consumed.
func (p *Parser) parseListUsersStatement() (*ListUsersStatement, error) {
return &ListUsersStatement{}, nil
}
// parseListFieldKeysStatement parses a string and returns a ListSeriesStatement. // parseListFieldKeysStatement parses a string and returns a ListSeriesStatement.
// This function assumes the "LIST FIELD KEYS" tokens have already been consumed. // This function assumes the "LIST FIELD KEYS" tokens have already been consumed.
func (p *Parser) parseListFieldKeysStatement() (*ListFieldKeysStatement, error) { func (p *Parser) parseListFieldKeysStatement() (*ListFieldKeysStatement, error) {

View File

@ -241,6 +241,12 @@ func TestParser_ParseStatement(t *testing.T) {
}, },
}, },
// LIST USERS
{
s: `LIST USERS`,
stmt: &influxql.ListUsersStatement{},
},
// LIST FIELD KEYS // LIST FIELD KEYS
{ {
s: `LIST FIELD KEYS FROM src WHERE region = 'uswest' ORDER BY ASC, field1, field2 DESC LIMIT 10`, s: `LIST FIELD KEYS FROM src WHERE region = 'uswest' ORDER BY ASC, field1, field2 DESC LIMIT 10`,

View File

@ -144,6 +144,7 @@ func TestScanner_Scan(t *testing.T) {
{s: `TAG`, tok: influxql.TAG}, {s: `TAG`, tok: influxql.TAG},
{s: `TO`, tok: influxql.TO}, {s: `TO`, tok: influxql.TO},
{s: `USER`, tok: influxql.USER}, {s: `USER`, tok: influxql.USER},
{s: `USERS`, tok: influxql.USERS},
{s: `VALUES`, tok: influxql.VALUES}, {s: `VALUES`, tok: influxql.VALUES},
{s: `WHERE`, tok: influxql.WHERE}, {s: `WHERE`, tok: influxql.WHERE},
{s: `WITH`, tok: influxql.WITH}, {s: `WITH`, tok: influxql.WITH},

View File

@ -99,6 +99,7 @@ const (
TAG TAG
TO TO
USER USER
USERS
VALUES VALUES
WHERE WHERE
WITH WITH
@ -187,6 +188,7 @@ var tokens = [...]string{
TAG: "TAG", TAG: "TAG",
TO: "TO", TO: "TO",
USER: "USER", USER: "USER",
USERS: "USERS",
VALUES: "VALUES", VALUES: "VALUES",
WHERE: "WHERE", WHERE: "WHERE",
WITH: "WITH", WITH: "WITH",