-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
Conversation
|
||
// 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 { |
There was a problem hiding this comment.
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"?
There was a problem hiding this comment.
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.
Makes sense at a first pass, but I think we're missing a chance to factor out some common code. Perhaps. |
+1 |
3f82cb0
to
d821f96
Compare
This should be changed to be for any aggregate function. This isn't specific to |
f9cef11
to
7963a85
Compare
…clause should fail
Did you mean to commit the |
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
count
=> aggregate
A couple small tweaks, but lgtm otherwise! |
no, I did not intend to commit |
@@ -295,6 +295,7 @@ func TestSelectStatement_HasWildcard(t *testing.T) { | |||
|
|||
for i, tt := range tests { | |||
// Parse statement. | |||
t.Logf("statement: %s", tt.stmt) |
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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.
+1, though the complex |
@@ -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)`, |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 :)
} | ||
|
||
// Validate checks certain edge conditions to determine if this is a valid select statment | ||
func (s *SelectStatement) Validate(tr targetRequirement) error { |
There was a problem hiding this comment.
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.
Throw parser error for aggregate functions with group by time without where time clause
this fixes #2444 |
If you issued a query like so:
It would effectively return an empty result set, but not error out.
This PR will now error out with:
The correct syntax is to provide a
WHERE
with atime
condition like so:Fixes #2542