-
Notifications
You must be signed in to change notification settings - Fork 24.9k
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
SQL: rewrite ROUND and TRUNCATE functions with a different optional parameter handling method #40242
Merged
Merged
SQL: rewrite ROUND and TRUNCATE functions with a different optional parameter handling method #40242
Changes from 2 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
4a88451
Rewrite Round and Truncate functions to have a slightly different
astefan 059b8f0
Merge branch 'master' of https://github.com/elastic/elasticsearch int…
astefan 7d5ce66
Addressing comments
astefan 0c2f559
Merge branch 'master' of https://github.com/elastic/elasticsearch int…
astefan 602c693
Merge branch 'master' of https://github.com/elastic/elasticsearch int…
astefan a0fa57b
Discard the use of one parameter Painless methods for Round and Truncate
astefan b81645e
Refactor the optional parameter Painless script in a separate method
astefan 3cc1bcc
Merge branch 'master' of https://github.com/elastic/elasticsearch int…
astefan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
115 changes: 115 additions & 0 deletions
115
...a/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryOptionalMathPipe.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
package org.elasticsearch.xpack.sql.expression.function.scalar.math; | ||
|
||
import org.elasticsearch.xpack.sql.execution.search.SqlSourceBuilder; | ||
import org.elasticsearch.xpack.sql.expression.Expression; | ||
import org.elasticsearch.xpack.sql.expression.function.scalar.math.BinaryOptionalMathProcessor.BinaryOptionalMathOperation; | ||
import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe; | ||
import org.elasticsearch.xpack.sql.tree.NodeInfo; | ||
import org.elasticsearch.xpack.sql.tree.Source; | ||
|
||
import java.util.Arrays; | ||
import java.util.List; | ||
import java.util.Objects; | ||
|
||
public class BinaryOptionalMathPipe extends Pipe { | ||
|
||
private final Pipe left, right; | ||
private final BinaryOptionalMathOperation operation; | ||
|
||
public BinaryOptionalMathPipe(Source source, Expression expression, Pipe left, Pipe right, BinaryOptionalMathOperation operation) { | ||
super(source, expression, right == null ? Arrays.asList(left) : Arrays.asList(left, right)); | ||
this.left = left; | ||
this.right = right; | ||
this.operation = operation; | ||
} | ||
|
||
@Override | ||
public final Pipe replaceChildren(List<Pipe> newChildren) { | ||
int childrenSize = newChildren.size(); | ||
if (childrenSize > 2 || childrenSize < 1) { | ||
throw new IllegalArgumentException("expected [1 or 2] children but received [" + newChildren.size() + "]"); | ||
} | ||
return replaceChildren(newChildren.get(0), childrenSize == 1 ? null : newChildren.get(1)); | ||
} | ||
|
||
@Override | ||
public final Pipe resolveAttributes(AttributeResolver resolver) { | ||
Pipe newLeft = left.resolveAttributes(resolver); | ||
Pipe newRight = right == null ? right : right.resolveAttributes(resolver); | ||
if (newLeft == left && newRight == right) { | ||
return this; | ||
} | ||
return replaceChildren(newLeft, newRight); | ||
} | ||
|
||
@Override | ||
public boolean supportedByAggsOnlyQuery() { | ||
return right == null ? left.supportedByAggsOnlyQuery() : left.supportedByAggsOnlyQuery() || right.supportedByAggsOnlyQuery(); | ||
} | ||
|
||
@Override | ||
public boolean resolved() { | ||
return left.resolved() && (right == null || right.resolved()); | ||
} | ||
|
||
protected Pipe replaceChildren(Pipe newLeft, Pipe newRight) { | ||
return new BinaryOptionalMathPipe(source(), expression(), newLeft, newRight, operation); | ||
} | ||
|
||
@Override | ||
public final void collectFields(SqlSourceBuilder sourceBuilder) { | ||
left.collectFields(sourceBuilder); | ||
if (right != null) { | ||
right.collectFields(sourceBuilder); | ||
} | ||
} | ||
|
||
@Override | ||
protected NodeInfo<BinaryOptionalMathPipe> info() { | ||
return NodeInfo.create(this, BinaryOptionalMathPipe::new, expression(), left, right, operation); | ||
} | ||
|
||
@Override | ||
public BinaryOptionalMathProcessor asProcessor() { | ||
return new BinaryOptionalMathProcessor(left.asProcessor(), right == null ? null : right.asProcessor(), operation); | ||
} | ||
|
||
public Pipe right() { | ||
return right; | ||
} | ||
|
||
public Pipe left() { | ||
return left; | ||
} | ||
|
||
public BinaryOptionalMathOperation operation() { | ||
return operation; | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(left, right, operation); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object obj) { | ||
if (this == obj) { | ||
return true; | ||
} | ||
|
||
if (obj == null || getClass() != obj.getClass()) { | ||
return false; | ||
} | ||
|
||
BinaryOptionalMathPipe other = (BinaryOptionalMathPipe) obj; | ||
return Objects.equals(left, other.left) | ||
&& Objects.equals(right, other.right) | ||
&& Objects.equals(operation, other.operation); | ||
} | ||
} |
154 changes: 154 additions & 0 deletions
154
.../elasticsearch/xpack/sql/expression/function/scalar/math/BinaryOptionalMathProcessor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
package org.elasticsearch.xpack.sql.expression.function.scalar.math; | ||
|
||
import org.elasticsearch.common.io.stream.StreamInput; | ||
import org.elasticsearch.common.io.stream.StreamOutput; | ||
import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; | ||
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor; | ||
|
||
import java.io.IOException; | ||
import java.util.Objects; | ||
import java.util.function.BiFunction; | ||
|
||
/** | ||
* Processor for binary mathematical operations that can have the second parameter optional. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe rephrase: ... that have a second optional parameter. |
||
*/ | ||
public class BinaryOptionalMathProcessor implements Processor { | ||
|
||
public enum BinaryOptionalMathOperation implements BiFunction<Number, Number, Number> { | ||
|
||
ROUND((l, r) -> { | ||
double tenAtScale = Math.pow(10., r.longValue()); | ||
double middleResult = l.doubleValue() * tenAtScale; | ||
int sign = middleResult > 0 ? 1 : -1; | ||
return Math.round(Math.abs(middleResult)) / tenAtScale * sign; | ||
}), | ||
TRUNCATE((l, r) -> { | ||
double tenAtScale = Math.pow(10., r.longValue()); | ||
double g = l.doubleValue() * tenAtScale; | ||
return (((l.doubleValue() < 0) ? Math.ceil(g) : Math.floor(g)) / tenAtScale); | ||
}); | ||
|
||
private final BiFunction<Number, Number, Number> process; | ||
|
||
BinaryOptionalMathOperation(BiFunction<Number, Number, Number> process) { | ||
this.process = process; | ||
} | ||
|
||
@Override | ||
public final Number apply(Number left, Number right) { | ||
if (left == null) { | ||
return null; | ||
} | ||
if (!(left instanceof Number)) { | ||
throw new SqlIllegalArgumentException("A number is required; received [{}]", left); | ||
} | ||
|
||
if (right != null) { | ||
if (!(right instanceof Number)) { | ||
throw new SqlIllegalArgumentException("A number is required; received [{}]", right); | ||
} | ||
if (right instanceof Float || right instanceof Double) { | ||
throw new SqlIllegalArgumentException("An integer number is required; received [{}] as second parameter", right); | ||
} | ||
} else { | ||
right = 0; | ||
} | ||
|
||
return process.apply(left, right); | ||
} | ||
} | ||
|
||
private final Processor left, right; | ||
private final BinaryOptionalMathOperation operation; | ||
public static final String NAME = "mob"; | ||
|
||
public BinaryOptionalMathProcessor(Processor left, Processor right, BinaryOptionalMathOperation operation) { | ||
this.left = left; | ||
this.right = right; | ||
this.operation = operation; | ||
} | ||
|
||
public BinaryOptionalMathProcessor(StreamInput in) throws IOException { | ||
left = in.readNamedWriteable(Processor.class); | ||
right = in.readOptionalNamedWriteable(Processor.class); | ||
operation = in.readEnum(BinaryOptionalMathOperation.class); | ||
} | ||
|
||
@Override | ||
public final void writeTo(StreamOutput out) throws IOException { | ||
out.writeNamedWriteable(left); | ||
out.writeOptionalNamedWriteable(right); | ||
out.writeEnum(operation); | ||
} | ||
|
||
@Override | ||
public Object process(Object input) { | ||
return doProcess(left().process(input), right() == null ? null : right().process(input)); | ||
} | ||
|
||
public Number doProcess(Object left, Object right) { | ||
if (left == null) { | ||
return null; | ||
} | ||
if (!(left instanceof Number)) { | ||
throw new SqlIllegalArgumentException("A number is required; received [{}]", left); | ||
} | ||
|
||
if (right != null) { | ||
if (!(right instanceof Number)) { | ||
throw new SqlIllegalArgumentException("A number is required; received [{}]", right); | ||
} | ||
if (right instanceof Float || right instanceof Double) { | ||
throw new SqlIllegalArgumentException("An integer number is required; received [{}] as second parameter", right); | ||
} | ||
} else { | ||
right = 0; | ||
} | ||
|
||
return operation().apply((Number) left, (Number) right); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object obj) { | ||
if (this == obj) { | ||
return true; | ||
} | ||
|
||
if (obj == null || getClass() != obj.getClass()) { | ||
return false; | ||
} | ||
|
||
BinaryOptionalMathProcessor other = (BinaryOptionalMathProcessor) obj; | ||
return Objects.equals(left(), other.left()) | ||
&& Objects.equals(right(), other.right()) | ||
&& Objects.equals(operation(), other.operation()); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(left(), right(), operation()); | ||
} | ||
|
||
public Processor left() { | ||
return left; | ||
} | ||
|
||
public Processor right() { | ||
return right; | ||
} | ||
|
||
public BinaryOptionalMathOperation operation() { | ||
return operation; | ||
} | ||
|
||
@Override | ||
public String getWriteableName() { | ||
return NAME; | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Can't this be tested in QueryTranslatorTests?