Skip to content

Commit

Permalink
Optimize CASE expressions on a constant
Browse files Browse the repository at this point in the history
If operand is a constant
    1. Remove the WhenClauses whose operand is constant and not equal to case operand
    2. If we find a WhenClause, whose constant operand equals to CASE constant operand, remove all the WhenClauses on its right and the default value.
  • Loading branch information
Xin Yao authored and cberner committed Jul 14, 2015
1 parent de0503e commit 24b3fdc
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 21 deletions.
Expand Up @@ -68,6 +68,7 @@
import java.util.HashSet; import java.util.HashSet;
import java.util.IdentityHashMap; import java.util.IdentityHashMap;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.stream.Stream; import java.util.stream.Stream;


Expand Down Expand Up @@ -279,38 +280,34 @@ protected Object visitSearchedCaseExpression(SearchedCaseExpression node, Object
protected Object visitSimpleCaseExpression(SimpleCaseExpression node, Object context) protected Object visitSimpleCaseExpression(SimpleCaseExpression node, Object context)
{ {
Object operand = process(node.getOperand(), context); Object operand = process(node.getOperand(), context);
if (operand instanceof Expression) { if (operand == null) {
// TODO: optimize this case return node.getDefaultValue().map(defaultValue -> process(defaultValue, context)).orElse(null);
}
else if (operand instanceof Expression) {
return node; return node;
} }


Expression resultClause = node.getDefaultValue().orElse(null); List<WhenClause> whenClauses = new ArrayList<>();
if (operand != null) { Expression defaultClause = node.getDefaultValue().orElse(null);
for (WhenClause whenClause : node.getWhenClauses()) { for (WhenClause whenClause : node.getWhenClauses()) {
Object value = process(whenClause.getOperand(), context); Object value = process(whenClause.getOperand(), context);
if (value == null) { if (value != null) {
continue;
}
if (value instanceof Expression) { if (value instanceof Expression) {
// TODO: optimize this case whenClauses.add(whenClause);
return node;
} }

else if ((Boolean) invokeOperator(OperatorType.EQUAL, types(node.getOperand(), whenClause.getOperand()), ImmutableList.of(operand, value))) {
if ((Boolean) invokeOperator(OperatorType.EQUAL, types(node.getOperand(), whenClause.getOperand()), ImmutableList.of(operand, value))) { defaultClause = whenClause.getResult();
resultClause = whenClause.getResult();
break; break;
} }
} }
} }
if (resultClause == null) {
return null;
}


Object result = process(resultClause, context); if (whenClauses.isEmpty()) {
if (result instanceof Expression) { return defaultClause == null ? null : process(defaultClause, context);
return node; }
else {
return new SimpleCaseExpression(node.getOperand(), whenClauses, Optional.ofNullable(defaultClause));
} }
return result;
} }


@Override @Override
Expand Down
Expand Up @@ -577,6 +577,27 @@ public void testSearchCase()
public void testSimpleCase() public void testSimpleCase()
throws Exception throws Exception
{ {
assertOptimizedEquals("case 1 " +
"when 1 then 33 " +
"when 1 then 34 " +
"end",
"33");

assertOptimizedEquals("case null " +
"when true then 33 " +
"end",
"null");
assertOptimizedEquals("case null " +
"when true then 33 " +
"else 33 " +
"end",
"33");
assertOptimizedEquals("case 33 " +
"when null then 1 " +
"else 33 " +
"end",
"33");

assertOptimizedEquals("case true " + assertOptimizedEquals("case true " +
"when true then 33 " + "when true then 33 " +
"end", "end",
Expand Down Expand Up @@ -629,6 +650,47 @@ public void testSimpleCase()
"when 1234 then 33 " + "when 1234 then 33 " +
"else 1 " + "else 1 " +
"end"); "end");

assertOptimizedEquals("case 33 " +
"when 0 then 0 " +
"when 33 then unbound_long " +
"else 1 " +
"end",
"unbound_long");
assertOptimizedEquals("case 33 " +
"when 0 then 0 " +
"when 33 then 1 " +
"when unbound_long then 2 " +
"else 1 " +
"end",
"1");
assertOptimizedEquals("case 33 " +
"when unbound_long then 0 " +
"when 1 then 1 " +
"when 33 then 2 " +
"else 0 " +
"end",
"case 33 " +
"when unbound_long then 0 " +
"else 2 " +
"end");
assertOptimizedEquals("case 33 " +
"when 0 then 0 " +
"when 1 then 1 " +
"else unbound_long " +
"end",
"unbound_long");
assertOptimizedEquals("case 33 " +
"when unbound_long then 0 " +
"when 1 then 1 " +
"when unbound_long2 then 2 " +
"else 3 " +
"end",
"case 33 " +
"when unbound_long then 0 " +
"when unbound_long2 then 2 " +
"else 3 " +
"end");
} }


@Test @Test
Expand Down

0 comments on commit 24b3fdc

Please sign in to comment.