Check database existence during normalization

Statements were only being normalized if a default database was included
in the query (usually via the query param 'db'). However if no default
database was included, and none was an explicit part of the measurement
name, no database-existence check was run. This result in a later panic
with wildcard expansion.
pull/2994/head
Philip O'Toole 2015-06-15 11:40:21 -07:00
parent e60645e1a2
commit 05bd0fc53d
2 changed files with 26 additions and 13 deletions

View File

@ -847,7 +847,7 @@ func TestServer_Query_Common(t *testing.T) {
&Query{ &Query{
name: "selecting a from a non-existent database should error", name: "selecting a from a non-existent database should error",
command: `SELECT value FROM db1.rp0.cpu`, command: `SELECT value FROM db1.rp0.cpu`,
exp: `{"results":[{"error":"database not found"}]}`, exp: `{"results":[{"error":"database not found: db1"}]}`,
}, },
&Query{ &Query{
name: "selecting a from a non-existent retention policy should error", name: "selecting a from a non-existent retention policy should error",
@ -870,6 +870,16 @@ func TestServer_Query_Common(t *testing.T) {
command: `SELECT idontexist FROM db0.rp0.cpu`, command: `SELECT idontexist FROM db0.rp0.cpu`,
exp: `{"results":[{"error":"unknown field or tag name in select clause: idontexist"}]}`, exp: `{"results":[{"error":"unknown field or tag name in select clause: idontexist"}]}`,
}, },
&Query{
name: "selecting wildcard without specifying a database should error",
command: `SELECT * FROM cpu`,
exp: `{"results":[{"error":"database name required"}]}`,
},
&Query{
name: "selecting explicit field without specifying a database should error",
command: `SELECT value FROM cpu`,
exp: `{"results":[{"error":"database name required"}]}`,
},
}...) }...)
if err := test.init(s); err != nil { if err := test.init(s); err != nil {

View File

@ -134,8 +134,9 @@ func (q *QueryExecutor) ExecuteQuery(query *influxql.Query, database string, chu
var i int var i int
var stmt influxql.Statement var stmt influxql.Statement
for i, stmt = range query.Statements { for i, stmt = range query.Statements {
// If a default database wasn't passed in by the caller, // If a default database wasn't passed in by the caller, check the statement.
// try to get it from the statement. // Some types of statements have an associated default database, even if it
// is not explicitly included.
defaultDB := database defaultDB := database
if defaultDB == "" { if defaultDB == "" {
if s, ok := stmt.(influxql.HasDefaultDatabase); ok { if s, ok := stmt.(influxql.HasDefaultDatabase); ok {
@ -143,12 +144,10 @@ func (q *QueryExecutor) ExecuteQuery(query *influxql.Query, database string, chu
} }
} }
// If we have a default database, normalize the statement with it. // Normalize each statement.
if defaultDB != "" { if err := q.normalizeStatement(stmt, defaultDB); err != nil {
if err := q.normalizeStatement(stmt, defaultDB); err != nil { results <- &influxql.Result{Err: err}
results <- &influxql.Result{Err: err} break
break
}
} }
var res *influxql.Result var res *influxql.Result
@ -905,19 +904,23 @@ func (q *QueryExecutor) normalizeStatement(stmt influxql.Statement, defaultDatab
return return
} }
// normalizeMeasurement inserts the default database or policy into all measurement names. // normalizeMeasurement inserts the default database or policy into all measurement names,
// if required.
func (q *QueryExecutor) normalizeMeasurement(m *influxql.Measurement, defaultDatabase string) error { func (q *QueryExecutor) normalizeMeasurement(m *influxql.Measurement, defaultDatabase string) error {
if defaultDatabase == "" {
return errors.New("no default database specified")
}
if m.Name == "" && m.Regex == nil { if m.Name == "" && m.Regex == nil {
return errors.New("invalid measurement") return errors.New("invalid measurement")
} }
// Measurement does not have an explicit database? Insert default.
if m.Database == "" { if m.Database == "" {
m.Database = defaultDatabase m.Database = defaultDatabase
} }
// The database must now be specified by this point.
if m.Database == "" {
return errors.New("database name required")
}
// Find database. // Find database.
di, err := q.MetaStore.Database(m.Database) di, err := q.MetaStore.Database(m.Database)
if err != nil { if err != nil {