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

Throw parser error for aggregate functions with group by time without where time clause #2540

Merged
merged 12 commits into from
May 12, 2015

Conversation

corylanou
Copy link
Contributor

If you issued a query like so:

select count(value) from cpu group by time(1d)

It would effectively return an empty result set, but not error out.

This PR will now error out with:

error parsing query: COUNT with GROUP BY time requires WHERE time clause

The correct syntax is to provide a WHERE with a time condition like so:

select count(value) from cpu where time > now() - 30d group by time(1d)

Fixes #2542


// hasWhereTime returns whether or not the select statement has at least 1
// where condition with time as the condition
func (s *SelectStatement) hasWhereTime(node Node) bool {
Copy link
Contributor

Choose a reason for hiding this comment

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

Very similar to OnlyTimeDimensions, but not exactly the same. Can we consolidate the two functions? Perhaps not. If nothing else, can we standardize on the term "time dimension"?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch. They are different methods, but I can line up the naming on them.

@otoolep
Copy link
Contributor

otoolep commented May 11, 2015

Makes sense at a first pass, but I think we're missing a chance to factor out some common code. Perhaps.

@toddboom
Copy link
Contributor

+1

@pauldix
Copy link
Member

pauldix commented May 11, 2015

This should be changed to be for any aggregate function. This isn't specific to count. Any time there is an aggregate with a GROUP BY time there needs to be a WHERE time ... clause.

@toddboom
Copy link
Contributor

Did you mean to commit the xxx.json file?

if d, _ := stmt.GroupByInterval(); stmt.IsRawQuery && d > 0 {
return nil, fmt.Errorf("GROUP BY requires at least one aggregate function")
}

// If we have a count function with a group by time without a where clause, it's an invalid statement
Copy link
Contributor

Choose a reason for hiding this comment

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

count => aggregate

@toddboom
Copy link
Contributor

A couple small tweaks, but lgtm otherwise!

@corylanou
Copy link
Contributor Author

no, I did not intend to commit xxx.json lol. Please send me the newbie award.

@@ -295,6 +295,7 @@ func TestSelectStatement_HasWildcard(t *testing.T) {

for i, tt := range tests {
// Parse statement.
t.Logf("statement: %s", tt.stmt)
Copy link
Contributor

Choose a reason for hiding this comment

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

If we're going to have this in the test output, can we at least at the testname and index, so the output has some context? Otherwise it just adds a lot of next-to useless noise to the test output. (IMHO).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can add the indexes, but those are typically the useless part for debugging, as counting down are pretty hard. Adding this line was what enabled me to easily search for and find the offending query. I believe our opinions differ :-).

if d, _ := stmt.GroupByInterval(); stmt.IsRawQuery && d > 0 {
return nil, fmt.Errorf("GROUP BY requires at least one aggregate function")
}

// If we have a count function with a group by time without a where clause, it's an invalid statement
if tr == targetNotRequired { // ignore create continuous query statements
if d, _ := stmt.GroupByInterval(); !stmt.IsRawQuery && d > 0 && !stmt.hasTimeDimensions(stmt.Condition) {
Copy link
Contributor

Choose a reason for hiding this comment

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

You sure this can't return an error? GroupByInternal() returns 0 if there is no GROUP BY? Do also really need IsRawQuery? I am curious.

@otoolep
Copy link
Contributor

otoolep commented May 12, 2015

+1, though the complex if statement tells me our AST code is definitely getting noisy, if you know what I mean.

@@ -258,7 +258,7 @@ func TestSelectStatement_HasWildcard(t *testing.T) {

// No GROUP BY wildcards, time only
{
stmt: `SELECT mean(value) FROM cpu GROUP BY time(5ms)`,
stmt: `SELECT mean(value) FROM cpu where time < now() GROUP BY time(5ms)`,
Copy link
Member

Choose a reason for hiding this comment

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

wait, how does this test pass? This should throw an error because you're asking for 5ms blocks from the beginning of time to now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@pauldix this is the parser only. It would certainly fail once it hit the query engine, which is a different test.

Copy link
Member

Choose a reason for hiding this comment

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

never mind, this is the ast test. Bounds get checked in the engine :)

@corylanou corylanou changed the title Throw parser error for invalid count group without where time Throw parser error for aggregate functions with group by time without where time clause May 12, 2015
}

// Validate checks certain edge conditions to determine if this is a valid select statment
func (s *SelectStatement) Validate(tr targetRequirement) error {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@otoolep I moved the if statements to their own function to clear up the parse function. Bottom line is if we want these checks, it requires if statements. I'm open to other suggestions if you feel the code is unbearable.

corylanou added a commit that referenced this pull request May 12, 2015
Throw parser error for aggregate functions with group by time without where time clause
@corylanou corylanou merged commit dca9859 into master May 12, 2015
@corylanou corylanou deleted the count-group-where branch May 12, 2015 15:20
@neonstalwart
Copy link
Contributor

this fixes #2444

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Throw parser error for invalid aggregate without where time
5 participants