Skip to content

Commit

Permalink
Encode varbinary literals as a function call to from_base64(...)
Browse files Browse the repository at this point in the history
They were being encoded using the "magic literal" hack, but the value
was being encoded as a UTF-8 string. The magic literal evaluator doesn't
know it has to reverse the process, so this ends up corrupting varbinary
literals during constant folding or distributed evaluation.

This minor hack turns varbinary literals into function calls to:

  from_base64(<base64-encoded varchar>)
  • Loading branch information
martint committed Jan 8, 2015
1 parent 5d7ad23 commit 52768fa
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.facebook.presto.metadata.FunctionRegistry;
import com.facebook.presto.metadata.Metadata;
import com.facebook.presto.metadata.Signature;
import com.facebook.presto.operator.scalar.VarbinaryFunctions;
import com.facebook.presto.spi.ConnectorSession;
import com.facebook.presto.spi.type.Type;
import com.facebook.presto.sql.analyzer.SemanticException;
Expand Down Expand Up @@ -46,6 +47,7 @@
import static com.facebook.presto.spi.type.BooleanType.BOOLEAN;
import static com.facebook.presto.spi.type.DoubleType.DOUBLE;
import static com.facebook.presto.spi.type.TypeSignature.parseTypeSignature;
import static com.facebook.presto.spi.type.VarbinaryType.VARBINARY;
import static com.facebook.presto.spi.type.VarcharType.VARCHAR;
import static com.facebook.presto.sql.analyzer.SemanticErrorCode.TYPE_MISMATCH;
import static com.facebook.presto.type.UnknownType.UNKNOWN;
Expand Down Expand Up @@ -134,6 +136,13 @@ else if (value.equals(Double.POSITIVE_INFINITY)) {
return new BooleanLiteral(object.toString());
}

if (type.equals(VARBINARY) && object instanceof Slice) {
// 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.
// We do this by transforming the in-memory varbinary into a call to from_base64(<base64-encoded value>)
return new FunctionCall(new QualifiedName("from_base64"), ImmutableList.of(new StringLiteral(VarbinaryFunctions.toBase64((Slice) object).toStringUtf8())));
}

Signature signature = FunctionRegistry.getMagicLiteralFunctionSignature(type);
Expression rawLiteral = toExpression(object, FunctionRegistry.type(type.getJavaType()));
return new FunctionCall(new QualifiedName(signature.getName()), ImmutableList.of(rawLiteral));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,14 @@ public void selectNull()
assertQuery("SELECT NULL", "SELECT NULL FROM (SELECT * FROM ORDERS LIMIT 1)");
}

@Test
public void testVarbinary()
throws Exception
{
assertQuery("SELECT LENGTH(x) FROM (SELECT from_base64('gw==') as x)", "SELECT 1");
assertQuery("SELECT LENGTH(from_base64('gw=='))", "SELECT 1");
}

@Test
public void testRowFieldAccessor()
throws Exception
Expand Down

0 comments on commit 52768fa

Please sign in to comment.