Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CREATE DATABASE [IF NOT EXISTS] ... #3892

Merged
merged 5 commits into from
Aug 29, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ With this release InfluxDB is moving to Go 1.5.

### Features
- [#3863](https://github.com/influxdb/influxdb/pull/3863): Move to Go 1.5
- [#3892](https://github.com/influxdb/influxdb/pull/3892): Support IF NOT EXISTS for CREATE DATABASE

### Bugfixes
- [#3804](https://github.com/influxdb/influxdb/pull/3804): init.d script fixes, fixes issue 3803.
Expand Down
22 changes: 21 additions & 1 deletion cmd/influxd/run/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,30 @@ func TestServer_DatabaseCommands(t *testing.T) {
exp: `{"results":[{"error":"database already exists"}]}`,
},
&Query{
name: "drop database should succeed",
name: "create database should not error with existing database with IF NOT EXISTS",
command: `CREATE DATABASE IF NOT EXISTS db0`,
exp: `{"results":[{}]}`,
},
&Query{
name: "create database should create non-existing database with IF NOT EXISTS",
command: `CREATE DATABASE IF NOT EXISTS db1`,
exp: `{"results":[{}]}`,
},
&Query{
name: "show database should succeed",
command: `SHOW DATABASES`,
exp: `{"results":[{"series":[{"name":"databases","columns":["name"],"values":[["db0"],["db1"]]}]}]}`,
},
&Query{
name: "drop database db0 should succeed",
command: `DROP DATABASE db0`,
exp: `{"results":[{}]}`,
},
&Query{
name: "drop database db1 should succeed",
command: `DROP DATABASE db1`,
exp: `{"results":[{}]}`,
},
&Query{
name: "show database should have no results",
command: `SHOW DATABASES`,
Expand Down
10 changes: 5 additions & 5 deletions influxql/INFLUXQL.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,11 @@ CREATE CONTINUOUS DATABASE DATABASES DEFAULT DELETE
DESC DROP DURATION END EXISTS EXPLAIN
FIELD FROM GRANT GROUP IF IN
INNER INSERT INTO KEY KEYS LIMIT
SHOW MEASUREMENT MEASUREMENTS OFFSET ON ORDER
PASSWORD POLICY POLICIES PRIVILEGES QUERIES QUERY
READ REPLICATION RETENTION REVOKE SELECT SERIES
SLIMIT SOFFSET TAG TO USER USERS
VALUES WHERE WITH WRITE
SHOW MEASUREMENT MEASUREMENTS NOT OFFSET ON
ORDER PASSWORD POLICY POLICIES PRIVILEGES QUERIES
QUERY READ REPLICATION RETENTION REVOKE SELECT
SERIES SLIMIT SOFFSET TAG TO USER
USERS VALUES WHERE WITH WRITE
```

## Literals
Expand Down
7 changes: 7 additions & 0 deletions influxql/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,12 +302,19 @@ func (a SortFields) String() string {
type CreateDatabaseStatement struct {
// Name of the database to be created.
Name string

// IfNotExists indicates whether to return without error if the database
// already exists.
IfNotExists bool
}

// String returns a string representation of the create database statement.
func (s *CreateDatabaseStatement) String() string {
var buf bytes.Buffer
_, _ = buf.WriteString("CREATE DATABASE ")
if s.IfNotExists {
_, _ = buf.WriteString("IF NOT EXISTS ")
}
_, _ = buf.WriteString(s.Name)
return buf.String()
}
Expand Down
10 changes: 10 additions & 0 deletions influxql/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -1250,6 +1250,16 @@ func (p *Parser) parseCreateContinuousQueryStatement() (*CreateContinuousQuerySt
func (p *Parser) parseCreateDatabaseStatement() (*CreateDatabaseStatement, error) {
stmt := &CreateDatabaseStatement{}

// Look for "IF NOT EXISTS"
if tok, _, _ := p.scanIgnoreWhitespace(); tok == IF {
if err := p.parseTokens([]Token{NOT, EXISTS}); err != nil {
return nil, err
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOT EXISTS parsing can be shortened to this...

if err := p.parseTokens([]Token{NOT, EXISTS}); err != nil {
   return nil, err
}

stmt.IfNotExists = true
} else {
p.unscan()
}

// Parse the name of the database to be created.
lit, err := p.parseIdent()
if err != nil {
Expand Down
14 changes: 13 additions & 1 deletion influxql/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,15 @@ func TestParser_ParseStatement(t *testing.T) {
{
s: `CREATE DATABASE testdb`,
stmt: &influxql.CreateDatabaseStatement{
Name: "testdb",
Name: "testdb",
IfNotExists: false,
},
},
{
s: `CREATE DATABASE IF NOT EXISTS testdb`,
stmt: &influxql.CreateDatabaseStatement{
Name: "testdb",
IfNotExists: true,
},
},

Expand Down Expand Up @@ -1276,6 +1284,10 @@ func TestParser_ParseStatement(t *testing.T) {
{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`},
{s: `DROP FOO`, err: `found FOO, expected SERIES, CONTINUOUS, MEASUREMENT at line 1, char 6`},
{s: `CREATE DATABASE`, err: `found EOF, expected identifier at line 1, char 17`},
{s: `CREATE DATABASE IF`, err: `found EOF, expected NOT at line 1, char 20`},
{s: `CREATE DATABASE IF NOT`, err: `found EOF, expected EXISTS at line 1, char 24`},
{s: `CREATE DATABASE IF NOT EXISTS`, err: `found EOF, expected identifier at line 1, char 31`},
{s: `DROP DATABASE`, err: `found EOF, expected identifier at line 1, char 15`},
{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`},
Expand Down
1 change: 1 addition & 0 deletions influxql/scanner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ func TestScanner_Scan(t *testing.T) {
{s: `SHOW`, tok: influxql.SHOW},
{s: `MEASUREMENT`, tok: influxql.MEASUREMENT},
{s: `MEASUREMENTS`, tok: influxql.MEASUREMENTS},
{s: `NOT`, tok: influxql.NOT},
{s: `OFFSET`, tok: influxql.OFFSET},
{s: `ON`, tok: influxql.ON},
{s: `ORDER`, tok: influxql.ORDER},
Expand Down
2 changes: 2 additions & 0 deletions influxql/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ const (
LIMIT
MEASUREMENT
MEASUREMENTS
NOT
OFFSET
ON
ORDER
Expand Down Expand Up @@ -198,6 +199,7 @@ var tokens = [...]string{
LIMIT: "LIMIT",
MEASUREMENT: "MEASUREMENT",
MEASUREMENTS: "MEASUREMENTS",
NOT: "NOT",
OFFSET: "OFFSET",
ON: "ON",
ORDER: "ORDER",
Expand Down
3 changes: 3 additions & 0 deletions meta/statement_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ func (e *StatementExecutor) ExecuteStatement(stmt influxql.Statement) *influxql.

func (e *StatementExecutor) executeCreateDatabaseStatement(q *influxql.CreateDatabaseStatement) *influxql.Result {
_, err := e.Store.CreateDatabase(q.Name)
if err == ErrDatabaseExists && q.IfNotExists {
err = nil
}
return &influxql.Result{Err: err}
}

Expand Down