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

QL: Turn eager query translations lazy #69205

Merged
merged 9 commits into from
Mar 2, 2021
Merged

Conversation

palesz
Copy link
Contributor

@palesz palesz commented Feb 18, 2021

Before the ExpressionTranslators did some unnecessary
Expression -> Query translations, where the result queries were thrown
away by later translations (by the wrapFunctionQuery).

This change adds laziness, so translations don't execute unnecessarily.

Follows #68783 and #68788


Note: #68788 (comment) requested more SqlTranslatorHandler tests, but the 9fc11a5 commit shows that the code is unreachable. Can only be reached when GeoDistanceQuery is generated and the test that generates a GeoDistanceQuery does not hit the line, so decided to remove it.

Andras Palinkas added 5 commits February 18, 2021 12:29
Before the `ExpressionTranslators` did some unnecessary
`Expression` -> `Query` translations, where the result queries were thrown
away by later translations (by the `wrapFunctionQuery`).

This change adds laziness, so translations don't execute unnecessarily.

Follows elastic#68783
* SqlTranslatorHandler dead code removal
* Pushed the common `wrapFunctionQuery` implementation into the TranslatorHandler
@palesz
Copy link
Contributor Author

palesz commented Feb 19, 2021

@elasticmachine run elasticsearch-ci/2

@palesz palesz added :Analytics/SQL SQL querying >refactoring Team:QL (Deprecated) Meta label for query languages team v7.13.0 v8.0.0 labels Feb 19, 2021
@palesz palesz marked this pull request as ready for review February 19, 2021 17:05
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-ql (Team:QL)

Copy link
Member

@costin costin left a comment

Choose a reason for hiding this comment

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

LGTM - however I'd like a few more tests. The changes are small but somewhat subtle and since some code is removed and as you pointed, unused, it would help to have more tests on the front (in this case geo) to avoid ending in a similar situation in the future as we're blind on that front.

@@ -1334,6 +1334,7 @@ public void testTranslateStDistanceToQuery() {
assertEquals(20.0, gq.lat(), 0.00001);
assertEquals(10.0, gq.lon(), 0.00001);
assertEquals(25.0, gq.distance(), 0.00001);
optimizeAndPlan(p);
Copy link
Member

Choose a reason for hiding this comment

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

? - there are no extra assertions after this call.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The optimizeAndPlan(p) was introduced as part of the 9fc11a5 commit to make sure we exercise the SqlTranslationHandler (the translate() does not do that) and check if it will produce a RuntimeException. Added an extra check on the generated query.

Added a test for the Verifier to capture the current behaviour: the WHERE ST_Distance(nested.point, ...) < X is not even allowed today (WHERE isn't (yet) compatible with scalar functions on nested fields).


private static Query translate(IsNotNull isNotNull, TranslatorHandler handler) {
Copy link
Member

Choose a reason for hiding this comment

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

Use a different name to avoid confusion, it's counter intuitive for doTranslate to call translate, I would have expected it to be the other way around.
Maybe createQuery or internalTranslate

Copy link
Contributor

Choose a reason for hiding this comment

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

+1

Copy link
Contributor

Choose a reason for hiding this comment

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

Might be a tad confusing, but this "doTranslate -> translate" pattern seems to be a pre-existing one.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As @bpintea pointed out the doTranslate / translate methods are pre-existing. I would do the renames in a separate PR across the all the translators and keep this PR focused only on laziness.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also fine for me, to address this later!

@@ -265,7 +271,7 @@ public static void checkBinaryComparison(BinaryComparison bc) {

public static Query doTranslate(BinaryComparison bc, TranslatorHandler handler) {
checkBinaryComparison(bc);
return handler.wrapFunctionQuery(bc, bc.left(), translate(bc, handler));
return handler.wrapFunctionQuery(bc, bc.left(), () -> translate(bc, handler));
Copy link
Member

Choose a reason for hiding this comment

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

Same here even though translate existed before it should be renamed.

Copy link
Contributor

@bpintea bpintea left a comment

Choose a reason for hiding this comment

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

LGTM


private static Query translate(IsNotNull isNotNull, TranslatorHandler handler) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Might be a tad confusing, but this "doTranslate -> translate" pattern seems to be a pre-existing one.

return ExpressionTranslator.wrapIfNested(querySupplier.get(), field);
}
return new ScriptQuery(sf.source(), sf.asScript());
}

String nameOf(Expression e);
Copy link
Contributor

Choose a reason for hiding this comment

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

Loosely coupled to this refactoring, but: couldn't nameOf() also be offered a static implementation here? All implementations could actually have it as a static method and SQL's (whose implementation lives actually in QueryTranslator) only treats the DateTimeFunction case additionally, compared to QL's.
So a bit more duplication could be stripped away.

Copy link
Contributor

@astefan astefan left a comment

Choose a reason for hiding this comment

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

Removing "dead" code without any good reason doesn't sound great from my side. The code has been added there with a good reason, hopefully; removing it should have an equally good reason, beside being "dead". I'd like a bit more investigation put into this issue to try and track down any refactoring (I'm mainly looking here at the split from one SQL project to QL/SQL/EQL) that could have led to this "dead" code now.

Maybe test the same 9fc11a5 commit in an older branch (before ql/sql/eql refactoring), or in the same commit that added the GEO part to SQL project. Maybe the code was added for no good reason since the beginning, maybe its utility faded with subsequent refactoring, but I think it's important to know why this code is dead now.

@palesz
Copy link
Contributor Author

palesz commented Mar 1, 2021

Removing "dead" code without any good reason doesn't sound great from my side. The code has been added there with a good reason, hopefully; removing it should have an equally good reason, beside being "dead". I'd like a bit more investigation put into this issue to try and track down any refactoring (I'm mainly looking here at the split from one SQL project to QL/SQL/EQL) that could have led to this "dead" code now.

Maybe test the same 9fc11a5 commit in an older branch (before ql/sql/eql refactoring), or in the same commit that added the GEO part to SQL project. Maybe the code was added for no good reason since the beginning, maybe its utility faded with subsequent refactoring, but I think it's important to know why this code is dead now.

@astefan See below.

  1. Since Jan, 2020 the following change does not allow scalar functions on nested fields, which means that the queries where the ST_Distance -> GeoDistanceQuery optimization could act on nested fields, don't even get to the QueryTranslator, rather fail early with WHERE isn't (yet) compatible with scalar functions on nested fields. Note: the translation still works as expected on non-nested fields.

  2. Even if the nested queries would pass the verifier, since the SQL -> QL/SQL refactor the optional wrapping into nested in case of nested fields is not called. As you can see, when I removed the dead code, I added back this optional potential nested query wrapped to the place where the optimized query is generated, so in case we remove the verifier checks a reasonable query translation will happen for the nested fields.

I'd open a separate issue if we decide to make this particular optimization work on nested fields again.

@matriv
Copy link
Contributor

matriv commented Mar 2, 2021

@palesz

Sounds good to me!

Copy link
Contributor

@astefan astefan left a comment

Choose a reason for hiding this comment

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

LGTM. Thank you @palesz

@palesz palesz merged commit 2dbd59b into elastic:master Mar 2, 2021
Copy link
Contributor

@matriv matriv left a comment

Choose a reason for hiding this comment

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

LGTM, delayed sorry :)

palesz pushed a commit to palesz/elasticsearch that referenced this pull request Mar 2, 2021
Before the `ExpressionTranslators` did some unnecessary
`Expression` -> `Query` translations, where the result queries were thrown
away by later translations (by the `wrapFunctionQuery`).

This change adds laziness, so translations don't execute unnecessarily.

Follows elastic#68783 and elastic#68788
palesz pushed a commit that referenced this pull request Mar 2, 2021
Before the `ExpressionTranslators` did some unnecessary
`Expression` -> `Query` translations, where the result queries were thrown
away by later translations (by the `wrapFunctionQuery`).

This change adds laziness, so translations don't execute unnecessarily.

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

Successfully merging this pull request may close these issues.

7 participants