-
Notifications
You must be signed in to change notification settings - Fork 25.6k
#46396 fix npe on ambiguous group by #56489
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
#46396 fix npe on ambiguous group by #56489
Conversation
|
Pinging @elastic/es-ql (:Query Languages/SQL) |
|
@verkhovin Thank you for picking this up! |
|
@matriv yes. Thank you |
|
@matriv please take a look, I've added a couple of tests. |
|
@elasticmachine test this please |
|
@verkhovin Could you also test with multiple agg functions with the same alias? |
|
@matriv i've found a problem. For the query but actual message is: Only two matches are represented in the message. |
|
Ok. It is because of Here I'm not sure if it should be fixed or it's expected behavior. |
| ex = expectThrows(VerificationException.class, | ||
| () -> plan("SELECT gender AS g, max(salary) AS g, min(salary) AS g FROM test GROUP BY g")); | ||
| assertEquals( | ||
| "Found 1 problem\nline 1:75: Reference [g] is ambiguous (to disambiguate use quotes or qualifiers); " + | ||
| "matches any of [\"g\", \"g\"]", | ||
| ex.getMessage()); |
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.
Here's where the problem is. This case passes because max(salary) AS g and min(salary) AS g are considered as equal Attributes (see my comment to the PR)
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.
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.
It's up to you. But I think such message would seem quite confusing. Imagine, you have really complex query with a lot of aliases, and only two of them are duplicated. I'd spend a lot of time to understand what such error message means.
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.
Oh, I see you changed Reference [] is ambiguous to Reference [g] is ambiguous in your comment. Sorry for the misunderstanding. If we specify which alias is ambiguous, than it lgfm.
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.
@bpintea what do you think?
Sounds good to me. I can't imagine a case where the "ambiguity count" is indispensable.
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.
Please note that the same error message (and same error message building implementation) is used in more complicated cases, e.g. here
Lines 189 to 193 in 378e087
| ex = expectThrows(VerificationException.class, () -> plan("SELECT test.test FROM test")); | |
| assertEquals( | |
| "Found 1 problem\nline 1:8: Reference [test.test] is ambiguous (to disambiguate use quotes or qualifiers); " | |
| + "matches any of [\"test\".\"test\", \"test\".\"test.test\"]", | |
| ex.getMessage()); |
|
Eventually i got rid of part of the message, which shows the "ambiguity count". |
|
@verkhovin Apologies for the delay on my response. After some discussion we decided that we shouldn't change the error message but instead handle the resolution differently. Here: https://github.com/elastic/elasticsearch/pull/56489/files#diff-bb55908282831d2f432f4a4650d55521L168 we pass the AttributeMap keySet where fields have been overriden because of it's special hashCode & equals implementation. We need to address it with a different approach with a List or a normal Set (if that works). Would you like to give that a try? otherwise we're happy to take it over from here as well. |
|
@matriv That's Great! I'm interested to finish it up in a right way, so I'll take a look on it. Thank you for your guidelines. I'll write here, if some help will be needed. |
|
@verkhovin Go ahead, thank you! |
|
@elasticmachine test this please |
|
@elasticmachine update branch |
|
@elasticmachine test this please |
|
Thank you @verkhovin for the new approach. |
|
@matriv do you mean we now can build such messages: I can try implement it in the current PR. Let me know if you think that it should be implemented as a separate feature in the scope of another PR |
|
@verkhovin Yes, that seems fine. You can include it in this PR. thx! |
|
@matriv please take a look |
matriv
left a comment
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.
Looks good overall, left some comments.
I'd like to ask you to add some tests for the ORDER by ambiguity.
Moreover, there is still an issue when you have duplicate aliases and using numeric references or the initial column names:
SELECT emp_no % languages as a, gender as a, max(salary) as a FROM test_emp GROUP BY 1, 2
or
SELECT emp_no % languages as a, gender as a, max(salary) as a FROM test_emp GROUP BY emp_no % languages, gender
both return an error like the following:
{
"error": {
"root_cause": [
{
"type": "sql_illegal_argument_exception",
"reason": "Cannot resolve field extractor index for column [a{r}#121]"
}
],
"type": "sql_illegal_argument_exception",
"reason": "Cannot resolve field extractor index for column [a{r}#121]"
},
"status": 500
}
Would you like to dig into it as well? (can also be done in a separate PR as the issue was already there, and not affected with your fix).
|
|
||
| import java.util.Objects; | ||
|
|
||
| public class AttributeAlias { |
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.
Could you please replace this with a Tuple<Attribute, Expression>?
| * The rest are not as they are not part of the projection and thus are not part of the derived table. | ||
| */ | ||
| public abstract class Attribute extends NamedExpression { | ||
| public abstract class Attribute extends NamedExpression implements Comparable<Attribute>{ |
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.
Making generic class Attribute to implement Comparable just for the purposes of constructing a nice error message is a bit too much. Please remove the comparison implementation from here and use a custom comparator to sort the ambiguous attributes.
| || Objects.equals(u.name(), attribute.qualifiedName())); | ||
| if (match) { | ||
| matches.add(attribute.withLocation(u.source())); | ||
| matches.add(attribute); |
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.
Why removing it from here and adding it only if matches.size() == 1?
| if (maybeResolved.resolved()) { | ||
| // use the matched expression (not its attribute) | ||
| grouping = resolved.stream() | ||
| .filter(attributeAlias -> attributeAlias.getAttribute().equals(maybeResolved)) |
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.
Imho, it would be better to use a for loop to increase readability.
|
@matriv thank you for the review and suggestions. I'll get to work on it in the nearest future.
Yeah, I am interested to dig into this after finishing the current PR. If you don't mind, I can create an issue about the error and self-assign it. |
|
@verkhovin FYI: #57668 If you feel like working on it, please feel free to assign yourself, but I'd like to ask you to finish up the work on this PR first. |
|
@matriv sure |
|
@verkhovin, many thanks for your contribution! Issue fixed by continuation PR #59370. |
|
Sorry for the latency. I really wanted to end up with it, but haven't enough time for that. |
Resolves #46396
After refactoring made in #49693 the issue is still reproducable.
I've append a bit of logic to ResolveRefs rule and now it seems to work as expected.
For the query
the following request body is returned:
I've run tests from
org.elasticsearch.xpack.sqlandprecommitgradle task to verify that everything is ok.Please, let me know if I missed something up.