Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
Expand All @@ -122,6 +123,7 @@
import static com.facebook.presto.sql.analyzer.ExpressionAnalyzer.createConstantAnalyzer;
import static com.facebook.presto.sql.analyzer.TypeSignatureProvider.fromTypes;
import static com.facebook.presto.sql.gen.VarArgsToMapAdapterGenerator.generateVarArgsToMapAdapter;
import static com.facebook.presto.sql.planner.DeterminismEvaluator.isDeterministic;
import static com.facebook.presto.sql.planner.iterative.rule.CanonicalizeExpressionRewriter.canonicalizeExpression;
import static com.facebook.presto.type.LikeFunctions.isLikePattern;
import static com.facebook.presto.type.LikeFunctions.unescapeLiteralLikePattern;
Expand All @@ -132,6 +134,7 @@
import static com.google.common.base.Throwables.throwIfInstanceOf;
import static com.google.common.base.Verify.verify;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.Iterables.getOnlyElement;
import static java.lang.String.format;
import static java.util.Objects.requireNonNull;

Expand Down Expand Up @@ -546,19 +549,37 @@ protected Object visitCoalesceExpression(CoalesceExpression node, Object context
List<Object> values = node.getOperands().stream()
.map(value -> processWithExceptionHandling(value, context))
.filter(Objects::nonNull)
.flatMap(expression -> {
if (expression instanceof CoalesceExpression) {
return ((CoalesceExpression) expression).getOperands().stream();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what if there are more levels of recursion? Make it recursive

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

But the current model is recursive right. We have added tests with more levels of coalesce and it passed it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It only supports one level of recursion.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Won't ExpressionInterpreter#processWithExceptionHandling will call other levels ? We just need to check if one of argument is of CoalesceExpression If yes we will extract its arguments and push it to the outer expression and processWithExceptionHandling will ideally handle at more levels

If I am not wrong recursive implementation will simplify
coalesce(coalesce(unbound_long, coalesce(unbound_long, 1)), unbound_long2) to coalesce(unbound_long, 1)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Right, thanks

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sorry I have replaced it with isDeterministic((CoalesceExpression) expression)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I mean I think that isDeterministic((CoalesceExpression) expression) can be removed completely. We don't need to check if nested coalesce is deterministic

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

But in that case it will simplify coalesce(unbound_long, coalesce(random(), 1) to coalesce(unbound_long, random(), 1).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@sopel39 Removed the deterministic check as it is not required now

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thank you. Ping us when release is done to land it

}
return Stream.of(expression);
})
.collect(Collectors.toList());

if ((!values.isEmpty() && !(values.get(0) instanceof Expression)) || values.size() == 1) {
return values.get(0);
}

List<Expression> expressions = values.stream()
.map(value -> toExpression(value, type))
.collect(Collectors.toList());
ImmutableList.Builder<Expression> operandsBuilder = ImmutableList.builder();
Set<Expression> visitedExpression = new HashSet<>();
for (Object value : values) {
Expression expression = toExpression(value, type);
Comment thread
Praveen2112 marked this conversation as resolved.
Outdated
if (!isDeterministic(expression) || visitedExpression.add(expression)) {
operandsBuilder.add(expression);
}
if (expression instanceof Literal) {
break;
}
}
List<Expression> expressions = operandsBuilder.build();

if (expressions.isEmpty()) {
return null;
}

if (expressions.size() == 1) {
return getOnlyElement(expressions);
}
return new CoalesceExpression(expressions);
}

Expand Down Expand Up @@ -642,7 +663,7 @@ else if (!found && result) {
.filter(DeterminismEvaluator::isDeterministic)
.distinct(),
expressionValues.stream()
.filter((expression -> !DeterminismEvaluator.isDeterministic(expression))))
.filter((expression -> !isDeterministic(expression))))
.collect(toImmutableList());
return new InPredicate(toExpression(value, type), new InListExpression(simplifiedExpressionValues));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ public class TestExpressionInterpreter
.put(new Symbol("unbound_integer"), INTEGER)
.put(new Symbol("unbound_long"), BIGINT)
.put(new Symbol("unbound_long2"), BIGINT)
.put(new Symbol("unbound_long3"), BIGINT)
.put(new Symbol("unbound_string"), VARCHAR)
.put(new Symbol("unbound_double"), DOUBLE)
.put(new Symbol("unbound_boolean"), BOOLEAN)
Expand Down Expand Up @@ -1136,7 +1137,19 @@ public void testCoalesce()
assertOptimizedEquals("coalesce(2 * 3 * unbound_integer, 1.0E0/2.0E0, null)", "coalesce(6 * unbound_integer, 0.5E0)");
assertOptimizedEquals("coalesce(unbound_integer, 2, 1.0E0/2.0E0, 12.34E0, null)", "coalesce(unbound_integer, 2.0E0, 0.5E0, 12.34E0)");
assertOptimizedMatches("coalesce(0 / 0 > 1, unbound_boolean, 0 / 0 = 0)",
"coalesce(cast(fail() as boolean), unbound_boolean, cast(fail() as boolean))");
"coalesce(cast(fail() as boolean), unbound_boolean)");
assertOptimizedMatches("coalesce(unbound_long, unbound_long)", "unbound_long");
assertOptimizedMatches("coalesce(2 * unbound_long, 2 * unbound_long)", "BIGINT '2' * unbound_long");
assertOptimizedMatches("coalesce(unbound_long, unbound_long2, unbound_long)", "coalesce(unbound_long, unbound_long2)");
assertOptimizedMatches("coalesce(unbound_long, unbound_long2, unbound_long, unbound_long3)", "coalesce(unbound_long, unbound_long2, unbound_long3)");
assertOptimizedEquals("coalesce(6, unbound_long2, unbound_long, unbound_long3)", "6");
assertOptimizedEquals("coalesce(2 * 3, unbound_long2, unbound_long, unbound_long3)", "6");
Comment thread
Praveen2112 marked this conversation as resolved.
Outdated
assertOptimizedMatches("coalesce(unbound_long, coalesce(unbound_long, 1))", "coalesce(unbound_long, BIGINT '1')");
assertOptimizedMatches("coalesce(coalesce(unbound_long, coalesce(unbound_long, 1)), unbound_long2)", "coalesce(unbound_long, BIGINT '1')");
assertOptimizedMatches("coalesce(unbound_long, 2, coalesce(unbound_long, 1))", "coalesce(unbound_long, BIGINT '2')");
assertOptimizedMatches("coalesce(coalesce(unbound_long, coalesce(unbound_long2, unbound_long3)), 1)", "coalesce(unbound_long, unbound_long2, unbound_long3, BIGINT '1')");
assertOptimizedMatches("coalesce(unbound_double, coalesce(random(), unbound_double))", "coalesce(unbound_double, random())");
assertOptimizedMatches("coalesce(random(), random(), 5)", "coalesce(random(), random(), 5E0)");
}

@Test
Expand Down