Skip to content

Commit

Permalink
Avoid unnecessary case transformation in QualifiedName
Browse files Browse the repository at this point in the history
  • Loading branch information
geraint0923 authored and martint committed Jun 20, 2016
1 parent 911f2b9 commit 6c8e64b
Show file tree
Hide file tree
Showing 11 changed files with 71 additions and 48 deletions.
Expand Up @@ -45,7 +45,7 @@ private static class Visitor
protected Void visitFunctionCall(FunctionCall node, AtomicBoolean deterministic) protected Void visitFunctionCall(FunctionCall node, AtomicBoolean deterministic)
{ {
// TODO: total hack to figure out if a function is deterministic. martint should fix this when he refactors the planning code // TODO: total hack to figure out if a function is deterministic. martint should fix this when he refactors the planning code
if (node.getName().equals(new QualifiedName("rand")) || node.getName().equals(new QualifiedName("random"))) { if (node.getName().equals(QualifiedName.of("rand")) || node.getName().equals(QualifiedName.of("random"))) {
deterministic.set(false); deterministic.set(false);
} }
return super.visitFunctionCall(node, deterministic); return super.visitFunctionCall(node, deterministic);
Expand Down
Expand Up @@ -138,13 +138,13 @@ public static Expression toExpression(Object object, Type type)
// if you remove this, you will need to update the TupleDomainOrcPredicate // if you remove this, you will need to update the TupleDomainOrcPredicate
// When changing this, don't forget about similar code for FLOAT below // When changing this, don't forget about similar code for FLOAT below
if (value.isNaN()) { if (value.isNaN()) {
return new FunctionCall(new QualifiedName("nan"), ImmutableList.<Expression>of()); return new FunctionCall(QualifiedName.of("nan"), ImmutableList.<Expression>of());
} }
else if (value.equals(Double.NEGATIVE_INFINITY)) { else if (value.equals(Double.NEGATIVE_INFINITY)) {
return ArithmeticUnaryExpression.negative(new FunctionCall(new QualifiedName("infinity"), ImmutableList.<Expression>of())); return ArithmeticUnaryExpression.negative(new FunctionCall(QualifiedName.of("infinity"), ImmutableList.<Expression>of()));
} }
else if (value.equals(Double.POSITIVE_INFINITY)) { else if (value.equals(Double.POSITIVE_INFINITY)) {
return new FunctionCall(new QualifiedName("infinity"), ImmutableList.<Expression>of()); return new FunctionCall(QualifiedName.of("infinity"), ImmutableList.<Expression>of());
} }
else { else {
return new DoubleLiteral(object.toString()); return new DoubleLiteral(object.toString());
Expand All @@ -155,13 +155,13 @@ else if (value.equals(Double.POSITIVE_INFINITY)) {
Float value = intBitsToFloat(((Long) object).intValue()); Float value = intBitsToFloat(((Long) object).intValue());
// WARNING for ORC predicate code as above (for double) // WARNING for ORC predicate code as above (for double)
if (value.isNaN()) { if (value.isNaN()) {
return new Cast(new FunctionCall(new QualifiedName("nan"), ImmutableList.of()), StandardTypes.FLOAT); return new Cast(new FunctionCall(QualifiedName.of("nan"), ImmutableList.of()), StandardTypes.FLOAT);
} }
else if (value.equals(Float.NEGATIVE_INFINITY)) { else if (value.equals(Float.NEGATIVE_INFINITY)) {
return ArithmeticUnaryExpression.negative(new Cast(new FunctionCall(new QualifiedName("infinity"), ImmutableList.of()), StandardTypes.FLOAT)); return ArithmeticUnaryExpression.negative(new Cast(new FunctionCall(QualifiedName.of("infinity"), ImmutableList.of()), StandardTypes.FLOAT));
} }
else if (value.equals(Float.POSITIVE_INFINITY)) { else if (value.equals(Float.POSITIVE_INFINITY)) {
return new Cast(new FunctionCall(new QualifiedName("infinity"), ImmutableList.of()), StandardTypes.FLOAT); return new Cast(new FunctionCall(QualifiedName.of("infinity"), ImmutableList.of()), StandardTypes.FLOAT);
} }
else { else {
return new GenericLiteral("FLOAT", value.toString()); return new GenericLiteral("FLOAT", value.toString());
Expand Down Expand Up @@ -202,15 +202,15 @@ else if (value.equals(Float.POSITIVE_INFINITY)) {
// HACK: we need to serialize VARBINARY in a format that can be embedded in an expression to be // HACK: we need to serialize VARBINARY in a format that can be embedded in an expression to be
// able to encode it in the plan that gets sent to workers. // able to encode it in the plan that gets sent to workers.
// We do this by transforming the in-memory varbinary into a call to from_base64(<base64-encoded value>) // We do this by transforming the in-memory varbinary into a call to from_base64(<base64-encoded value>)
FunctionCall fromBase64 = new FunctionCall(new QualifiedName("from_base64"), ImmutableList.of(new StringLiteral(VarbinaryFunctions.toBase64((Slice) object).toStringUtf8()))); FunctionCall fromBase64 = new FunctionCall(QualifiedName.of("from_base64"), ImmutableList.of(new StringLiteral(VarbinaryFunctions.toBase64((Slice) object).toStringUtf8())));
Signature signature = FunctionRegistry.getMagicLiteralFunctionSignature(type); Signature signature = FunctionRegistry.getMagicLiteralFunctionSignature(type);
return new FunctionCall(new QualifiedName(signature.getName()), ImmutableList.of(fromBase64)); return new FunctionCall(QualifiedName.of(signature.getName()), ImmutableList.of(fromBase64));
} }


Signature signature = FunctionRegistry.getMagicLiteralFunctionSignature(type); Signature signature = FunctionRegistry.getMagicLiteralFunctionSignature(type);
Expression rawLiteral = toExpression(object, FunctionRegistry.typeForMagicLiteral(type)); Expression rawLiteral = toExpression(object, FunctionRegistry.typeForMagicLiteral(type));


return new FunctionCall(new QualifiedName(signature.getName()), ImmutableList.of(rawLiteral)); return new FunctionCall(QualifiedName.of(signature.getName()), ImmutableList.of(rawLiteral));
} }


private static class LiteralVisitor private static class LiteralVisitor
Expand Down
Expand Up @@ -137,15 +137,15 @@ public Expression rewriteCurrentTime(CurrentTime node, Void context, ExpressionT


switch (node.getType()) { switch (node.getType()) {
case DATE: case DATE:
return new FunctionCall(new QualifiedName("current_date"), ImmutableList.<Expression>of()); return new FunctionCall(QualifiedName.of("current_date"), ImmutableList.<Expression>of());
case TIME: case TIME:
return new FunctionCall(new QualifiedName("current_time"), ImmutableList.<Expression>of()); return new FunctionCall(QualifiedName.of("current_time"), ImmutableList.<Expression>of());
case LOCALTIME: case LOCALTIME:
return new FunctionCall(new QualifiedName("localtime"), ImmutableList.<Expression>of()); return new FunctionCall(QualifiedName.of("localtime"), ImmutableList.<Expression>of());
case TIMESTAMP: case TIMESTAMP:
return new FunctionCall(new QualifiedName("current_timestamp"), ImmutableList.<Expression>of()); return new FunctionCall(QualifiedName.of("current_timestamp"), ImmutableList.<Expression>of());
case LOCALTIMESTAMP: case LOCALTIMESTAMP:
return new FunctionCall(new QualifiedName("localtimestamp"), ImmutableList.<Expression>of()); return new FunctionCall(QualifiedName.of("localtimestamp"), ImmutableList.<Expression>of());
default: default:
throw new UnsupportedOperationException("not yet implemented: " + node.getType()); throw new UnsupportedOperationException("not yet implemented: " + node.getType());
} }
Expand All @@ -158,35 +158,35 @@ public Expression rewriteExtract(Extract node, Void context, ExpressionTreeRewri


switch (node.getField()) { switch (node.getField()) {
case YEAR: case YEAR:
return new FunctionCall(new QualifiedName("year"), ImmutableList.of(value)); return new FunctionCall(QualifiedName.of("year"), ImmutableList.of(value));
case QUARTER: case QUARTER:
return new FunctionCall(new QualifiedName("quarter"), ImmutableList.of(value)); return new FunctionCall(QualifiedName.of("quarter"), ImmutableList.of(value));
case MONTH: case MONTH:
return new FunctionCall(new QualifiedName("month"), ImmutableList.of(value)); return new FunctionCall(QualifiedName.of("month"), ImmutableList.of(value));
case WEEK: case WEEK:
return new FunctionCall(new QualifiedName("week"), ImmutableList.of(value)); return new FunctionCall(QualifiedName.of("week"), ImmutableList.of(value));
case DAY: case DAY:
case DAY_OF_MONTH: case DAY_OF_MONTH:
return new FunctionCall(new QualifiedName("day"), ImmutableList.of(value)); return new FunctionCall(QualifiedName.of("day"), ImmutableList.of(value));
case DAY_OF_WEEK: case DAY_OF_WEEK:
case DOW: case DOW:
return new FunctionCall(new QualifiedName("day_of_week"), ImmutableList.of(value)); return new FunctionCall(QualifiedName.of("day_of_week"), ImmutableList.of(value));
case DAY_OF_YEAR: case DAY_OF_YEAR:
case DOY: case DOY:
return new FunctionCall(new QualifiedName("day_of_year"), ImmutableList.of(value)); return new FunctionCall(QualifiedName.of("day_of_year"), ImmutableList.of(value));
case YEAR_OF_WEEK: case YEAR_OF_WEEK:
case YOW: case YOW:
return new FunctionCall(new QualifiedName("year_of_week"), ImmutableList.of(value)); return new FunctionCall(QualifiedName.of("year_of_week"), ImmutableList.of(value));
case HOUR: case HOUR:
return new FunctionCall(new QualifiedName("hour"), ImmutableList.of(value)); return new FunctionCall(QualifiedName.of("hour"), ImmutableList.of(value));
case MINUTE: case MINUTE:
return new FunctionCall(new QualifiedName("minute"), ImmutableList.of(value)); return new FunctionCall(QualifiedName.of("minute"), ImmutableList.of(value));
case SECOND: case SECOND:
return new FunctionCall(new QualifiedName("second"), ImmutableList.of(value)); return new FunctionCall(QualifiedName.of("second"), ImmutableList.of(value));
case TIMEZONE_MINUTE: case TIMEZONE_MINUTE:
return new FunctionCall(new QualifiedName("timezone_minute"), ImmutableList.of(value)); return new FunctionCall(QualifiedName.of("timezone_minute"), ImmutableList.of(value));
case TIMEZONE_HOUR: case TIMEZONE_HOUR:
return new FunctionCall(new QualifiedName("timezone_hour"), ImmutableList.of(value)); return new FunctionCall(QualifiedName.of("timezone_hour"), ImmutableList.of(value));
} }


throw new UnsupportedOperationException("not yet implemented: " + node.getField()); throw new UnsupportedOperationException("not yet implemented: " + node.getField());
Expand Down
Expand Up @@ -69,7 +69,7 @@ public void testSetSession()
throws Exception throws Exception
{ {
testSetSession(new StringLiteral("baz"), "baz"); testSetSession(new StringLiteral("baz"), "baz");
testSetSession(new FunctionCall(new QualifiedName("concat"), ImmutableList.of( testSetSession(new FunctionCall(QualifiedName.of("concat"), ImmutableList.of(
new StringLiteral("ban"), new StringLiteral("ban"),
new StringLiteral("ana"))), "banana"); new StringLiteral("ana"))), "banana");
} }
Expand Down
Expand Up @@ -39,7 +39,7 @@ public void testSanity()


private static FunctionCall function(String name, Expression... inputs) private static FunctionCall function(String name, Expression... inputs)
{ {
return new FunctionCall(new QualifiedName(name), Arrays.asList(inputs)); return new FunctionCall(QualifiedName.of(name), Arrays.asList(inputs));
} }


private static QualifiedNameReference input(String symbol) private static QualifiedNameReference input(String symbol)
Expand Down
Expand Up @@ -1342,7 +1342,7 @@ private static Expression unprocessableExpression2(Symbol symbol)


private static Expression randPredicate(Symbol symbol) private static Expression randPredicate(Symbol symbol)
{ {
return comparison(GREATER_THAN, symbol.toSymbolReference(), new FunctionCall(new QualifiedName("rand"), ImmutableList.<Expression>of())); return comparison(GREATER_THAN, symbol.toSymbolReference(), new FunctionCall(QualifiedName.of("rand"), ImmutableList.<Expression>of()));
} }


private static NotExpression not(Expression expression) private static NotExpression not(Expression expression)
Expand Down
Expand Up @@ -113,7 +113,7 @@ public static Expression caseWhen(Expression operand, Expression result)


public static Expression functionCall(String name, Expression... arguments) public static Expression functionCall(String name, Expression... arguments)
{ {
return new FunctionCall(new QualifiedName(name), ImmutableList.copyOf(arguments)); return new FunctionCall(QualifiedName.of(name), ImmutableList.copyOf(arguments));
} }


public static Values values(Row... row) public static Values values(Row... row)
Expand Down
Expand Up @@ -974,7 +974,7 @@ public Node visitConcatenation(SqlBaseParser.ConcatenationContext context)
{ {
return new FunctionCall( return new FunctionCall(
getLocation(context.CONCAT()), getLocation(context.CONCAT()),
new QualifiedName("concat"), ImmutableList.of( QualifiedName.of("concat"), ImmutableList.of(
(Expression) visit(context.left), (Expression) visit(context.left),
(Expression) visit(context.right))); (Expression) visit(context.right)));
} }
Expand Down Expand Up @@ -1056,22 +1056,22 @@ public Node visitExtract(SqlBaseParser.ExtractContext context)
@Override @Override
public Node visitSubstring(SqlBaseParser.SubstringContext context) public Node visitSubstring(SqlBaseParser.SubstringContext context)
{ {
return new FunctionCall(getLocation(context), new QualifiedName("substr"), visit(context.valueExpression(), Expression.class)); return new FunctionCall(getLocation(context), QualifiedName.of("substr"), visit(context.valueExpression(), Expression.class));
} }


@Override @Override
public Node visitPosition(SqlBaseParser.PositionContext context) public Node visitPosition(SqlBaseParser.PositionContext context)
{ {
List<Expression> arguments = Lists.reverse(visit(context.valueExpression(), Expression.class)); List<Expression> arguments = Lists.reverse(visit(context.valueExpression(), Expression.class));
return new FunctionCall(getLocation(context), new QualifiedName("strpos"), arguments); return new FunctionCall(getLocation(context), QualifiedName.of("strpos"), arguments);
} }


@Override @Override
public Node visitNormalize(SqlBaseParser.NormalizeContext context) public Node visitNormalize(SqlBaseParser.NormalizeContext context)
{ {
Expression str = (Expression) visit(context.valueExpression()); Expression str = (Expression) visit(context.valueExpression());
String normalForm = Optional.ofNullable(context.normalForm()).map(ParserRuleContext::getText).orElse("NFC"); String normalForm = Optional.ofNullable(context.normalForm()).map(ParserRuleContext::getText).orElse("NFC");
return new FunctionCall(getLocation(context), new QualifiedName("normalize"), ImmutableList.of(str, new StringLiteral(getLocation(context), normalForm))); return new FunctionCall(getLocation(context), QualifiedName.of("normalize"), ImmutableList.of(str, new StringLiteral(getLocation(context), normalForm)));
} }


@Override @Override
Expand All @@ -1095,7 +1095,7 @@ public Node visitDereference(SqlBaseParser.DereferenceContext context)
@Override @Override
public Node visitColumnReference(SqlBaseParser.ColumnReferenceContext context) public Node visitColumnReference(SqlBaseParser.ColumnReferenceContext context)
{ {
return new QualifiedNameReference(getLocation(context), new QualifiedName(context.getText())); return new QualifiedNameReference(getLocation(context), QualifiedName.of(context.getText()));
} }


@Override @Override
Expand Down Expand Up @@ -1387,7 +1387,7 @@ private static QualifiedName getQualifiedName(SqlBaseParser.QualifiedNameContext
.map(ParseTree::getText) .map(ParseTree::getText)
.collect(toList()); .collect(toList());


return new QualifiedName(parts); return QualifiedName.of(parts);
} }


private static boolean isDistinct(SqlBaseParser.SetQuantifierContext setQuantifier) private static boolean isDistinct(SqlBaseParser.SetQuantifierContext setQuantifier)
Expand Down
Expand Up @@ -69,7 +69,7 @@ public String getFieldName()
public static QualifiedName getQualifiedName(DereferenceExpression expression) public static QualifiedName getQualifiedName(DereferenceExpression expression)
{ {
List<String> parts = tryParseParts(expression.base, expression.fieldName); List<String> parts = tryParseParts(expression.base, expression.fieldName);
return parts == null ? null : new QualifiedName(parts); return parts == null ? null : QualifiedName.of(parts);
} }


private static List<String> tryParseParts(Expression base, String fieldName) private static List<String> tryParseParts(Expression base, String fieldName)
Expand Down
Expand Up @@ -35,20 +35,28 @@ public class QualifiedName
public static QualifiedName of(String first, String... rest) public static QualifiedName of(String first, String... rest)
{ {
requireNonNull(first, "first is null"); requireNonNull(first, "first is null");
return new QualifiedName(ImmutableList.copyOf(Lists.asList(first, rest))); return of(ImmutableList.copyOf(Lists.asList(first, rest)));
} }


public QualifiedName(String name) public static QualifiedName of(String name)
{ {
this(ImmutableList.of(name)); requireNonNull(name, "name is null");
return of(ImmutableList.of(name));
} }


public QualifiedName(Iterable<String> parts) public static QualifiedName of(Iterable<String> originalParts)
{ {
requireNonNull(parts, "parts is null"); requireNonNull(originalParts, "originalParts is null");
checkArgument(!isEmpty(parts), "parts is empty"); checkArgument(!isEmpty(originalParts), "originalParts is empty");
this.parts = ImmutableList.copyOf(transform(parts, part -> part.toLowerCase(ENGLISH))); List<String> parts = ImmutableList.copyOf(transform(originalParts, part -> part.toLowerCase(ENGLISH)));
this.originalParts = ImmutableList.copyOf(parts);
return new QualifiedName(ImmutableList.copyOf(originalParts), parts);
}

private QualifiedName(List<String> originalParts, List<String> parts)
{
this.originalParts = originalParts;
this.parts = parts;
} }


public List<String> getParts() public List<String> getParts()
Expand Down Expand Up @@ -77,7 +85,8 @@ public Optional<QualifiedName> getPrefix()
return Optional.empty(); return Optional.empty();
} }


return Optional.of(new QualifiedName(parts.subList(0, parts.size() - 1))); List<String> subList = parts.subList(0, parts.size() - 1);
return Optional.of(new QualifiedName(subList, subList));
} }


public boolean hasSuffix(QualifiedName suffix) public boolean hasSuffix(QualifiedName suffix)
Expand Down
Expand Up @@ -121,6 +121,8 @@
import static java.lang.String.format; import static java.lang.String.format;
import static java.util.Collections.nCopies; import static java.util.Collections.nCopies;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail; import static org.testng.Assert.fail;


public class TestSqlParser public class TestSqlParser
Expand Down Expand Up @@ -149,6 +151,18 @@ public void testPossibleExponentialBacktracking()
SQL_PARSER.createExpression("(((((((((((((((((((((((((((true)))))))))))))))))))))))))))"); SQL_PARSER.createExpression("(((((((((((((((((((((((((((true)))))))))))))))))))))))))))");
} }


@Test
public void testQualifiedName()
{
assertEquals(QualifiedName.of("a", "b", "c", "d").toString(), "a.b.c.d");
assertEquals(QualifiedName.of("A", "b", "C", "d").toString(), "a.b.c.d");
assertTrue(QualifiedName.of("a", "b", "c", "d").hasSuffix(QualifiedName.of("b", "c", "d")));
assertTrue(QualifiedName.of("a", "b", "c", "d").hasSuffix(QualifiedName.of("a", "b", "c", "d")));
assertFalse(QualifiedName.of("a", "b", "c", "d").hasSuffix(QualifiedName.of("a", "c", "d")));
assertFalse(QualifiedName.of("a", "b", "c", "d").hasSuffix(QualifiedName.of("z", "a", "b", "c", "d")));
assertEquals(QualifiedName.of("a", "b", "c", "d"), QualifiedName.of("a", "b", "c", "d"));
}

@Test @Test
public void testGenericLiteral() public void testGenericLiteral()
throws Exception throws Exception
Expand Down

0 comments on commit 6c8e64b

Please sign in to comment.