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 @@ -299,6 +299,7 @@
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.TypeSignatureProvider.fromTypeSignatures;
import static com.facebook.presto.sql.analyzer.TypeSignatureProvider.fromTypes;
import static com.facebook.presto.type.DecimalCasts.BIGINT_TO_DECIMAL_CAST;
Expand Down Expand Up @@ -1107,6 +1108,21 @@ public Signature getCoercion(TypeSignature fromType, TypeSignature toType)
return signature;
}

public Signature resolveConstructor(Type type)
{
Signature signature = internalOperator(OperatorType.CONSTRUCT, type, ImmutableList.of(VARCHAR));
try {
getScalarFunctionImplementation(signature);
}
catch (PrestoException e) {
if (e.getErrorCode().getCode() == FUNCTION_IMPLEMENTATION_MISSING.toErrorCode().getCode()) {
return getCoercion(VARCHAR, type);
}
throw e;
}
return signature;
}

public static Type typeForMagicLiteral(Type type)
{
Class<?> clazz = type.getJavaType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import java.util.List;

import static com.facebook.presto.spi.StandardErrorCode.INVALID_FUNCTION_ARGUMENT;
import static com.facebook.presto.spi.function.OperatorType.CONSTRUCT;
import static com.facebook.presto.spi.type.Chars.padSpaces;
import static com.facebook.presto.util.JsonUtil.createJsonParser;
import static com.facebook.presto.util.JsonUtil.truncateIfNecessaryForErrorMessage;
Expand Down Expand Up @@ -134,6 +135,7 @@ public static Slice jsonFormat(@SqlType(StandardTypes.JSON) Slice slice)
return slice;
}

@ScalarOperator(CONSTRUCT)
@ScalarFunction
@LiteralParameters("x")
@SqlType(StandardTypes.JSON)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ public static void validateOperator(OperatorType operatorType, TypeSignature ret
case CAST:
validateOperatorSignature(operatorType, returnType, argumentTypes, 1);
break;
case CONSTRUCT:
validateOperatorSignature(operatorType, returnType, argumentTypes, 1);
checkArgument(argumentTypes.get(0).getBase().equalsIgnoreCase(StandardTypes.VARCHAR), "Argument must be a VARCHAR");
break;
case SUBSCRIPT:
validateOperatorSignature(operatorType, returnType, argumentTypes, 2);
checkArgument(argumentTypes.get(0).getBase().equals(StandardTypes.ARRAY) || argumentTypes.get(0).getBase().equals(StandardTypes.MAP), "First argument must be an ARRAY or MAP");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@
import static com.facebook.presto.type.ArrayParametricType.ARRAY;
import static com.facebook.presto.type.IntervalDayTimeType.INTERVAL_DAY_TIME;
import static com.facebook.presto.type.IntervalYearMonthType.INTERVAL_YEAR_MONTH;
import static com.facebook.presto.type.JsonType.JSON;
import static com.facebook.presto.type.UnknownType.UNKNOWN;
import static com.facebook.presto.util.DateTimeUtils.parseTimestampLiteral;
import static com.facebook.presto.util.DateTimeUtils.timeHasTimeZone;
Expand Down Expand Up @@ -721,13 +720,11 @@ protected Type visitGenericLiteral(GenericLiteral node, StackableAstVisitorConte
throw new SemanticException(TYPE_MISMATCH, node, "Unknown type: " + node.getType());
}

if (!JSON.equals(type)) {
try {
functionRegistry.getCoercion(VARCHAR, type);
}
catch (IllegalArgumentException e) {
throw new SemanticException(TYPE_MISMATCH, node, "No literal form for type %s", type);
}
try {
functionRegistry.resolveConstructor(type);
}
catch (IllegalArgumentException e) {
throw new SemanticException(TYPE_MISMATCH, node, "No literal form for type %s", type);
}

return setExpressionType(node, type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,9 @@
import com.google.common.collect.ImmutableList;
import io.airlift.slice.Slice;

import static com.facebook.presto.metadata.FunctionKind.SCALAR;
import static com.facebook.presto.spi.type.TypeSignature.parseTypeSignature;
import static com.facebook.presto.spi.type.VarcharType.VARCHAR;
import static com.facebook.presto.sql.analyzer.SemanticErrorCode.INVALID_LITERAL;
import static com.facebook.presto.sql.analyzer.SemanticErrorCode.TYPE_MISMATCH;
import static com.facebook.presto.type.JsonType.JSON;
import static com.facebook.presto.util.DateTimeUtils.parseDayTimeInterval;
import static com.facebook.presto.util.DateTimeUtils.parseTimeLiteral;
import static com.facebook.presto.util.DateTimeUtils.parseTimestampLiteral;
Expand Down Expand Up @@ -130,13 +127,8 @@ protected Object visitGenericLiteral(GenericLiteral node, ConnectorSession sessi
throw new SemanticException(TYPE_MISMATCH, node, "Unknown type: " + node.getType());
}

if (JSON.equals(type)) {
Signature operatorSignature = new Signature("json_parse", SCALAR, JSON.getTypeSignature(), VARCHAR.getTypeSignature());
return functionInvoker.invoke(operatorSignature, session, ImmutableList.of(utf8Slice(node.getValue())));
}

try {
Signature signature = metadata.getFunctionRegistry().getCoercion(VARCHAR, type);
Signature signature = metadata.getFunctionRegistry().resolveConstructor(type);
return functionInvoker.invoke(signature, session, ImmutableList.of(utf8Slice(node.getValue())));
}
catch (IllegalArgumentException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@
import java.util.OptionalInt;

import static com.facebook.presto.SystemSessionProperties.isLegacyRowFieldOrdinalAccessEnabled;
import static com.facebook.presto.metadata.FunctionKind.SCALAR;
import static com.facebook.presto.spi.type.BigintType.BIGINT;
import static com.facebook.presto.spi.type.BooleanType.BOOLEAN;
import static com.facebook.presto.spi.type.CharType.createCharType;
Expand Down Expand Up @@ -118,7 +117,6 @@
import static com.facebook.presto.sql.relational.Signatures.switchSignature;
import static com.facebook.presto.sql.relational.Signatures.tryCastSignature;
import static com.facebook.presto.sql.relational.Signatures.whenSignature;
import static com.facebook.presto.type.JsonType.JSON;
import static com.facebook.presto.type.LikePatternType.LIKE_PATTERN;
import static com.facebook.presto.util.DateTimeUtils.parseDayTimeInterval;
import static com.facebook.presto.util.DateTimeUtils.parseTimeWithTimeZone;
Expand Down Expand Up @@ -149,6 +147,7 @@ public static RowExpression translate(
Visitor visitor = new Visitor(
functionKind,
types,
functionRegistry,
typeManager,
session.getTimeZoneKey(),
isLegacyRowFieldOrdinalAccessEnabled(session),
Expand All @@ -170,6 +169,7 @@ private static class Visitor
{
private final FunctionKind functionKind;
private final Map<NodeRef<Expression>, Type> types;
private final FunctionRegistry functionRegistry;
private final TypeManager typeManager;
private final TimeZoneKey timeZoneKey;
private final boolean legacyRowFieldOrdinalAccess;
Expand All @@ -179,13 +179,15 @@ private static class Visitor
private Visitor(
FunctionKind functionKind,
Map<NodeRef<Expression>, Type> types,
FunctionRegistry functionRegistry,
TypeManager typeManager,
TimeZoneKey timeZoneKey,
boolean legacyRowFieldOrdinalAccess,
boolean isLegacyTimestamp)
{
this.functionKind = functionKind;
this.types = ImmutableMap.copyOf(requireNonNull(types, "types is null"));
this.functionRegistry = functionRegistry;
this.typeManager = typeManager;
this.timeZoneKey = timeZoneKey;
this.legacyRowFieldOrdinalAccess = legacyRowFieldOrdinalAccess;
Expand Down Expand Up @@ -272,15 +274,8 @@ protected RowExpression visitGenericLiteral(GenericLiteral node, Void context)
throw new IllegalArgumentException("Unsupported type: " + node.getType());
}

if (JSON.equals(type)) {
return call(
new Signature("json_parse", SCALAR, getType(node).getTypeSignature(), VARCHAR.getTypeSignature()),
getType(node),
constant(utf8Slice(node.getValue()), VARCHAR));
}

return call(
castSignature(getType(node), VARCHAR),
functionRegistry.resolveConstructor(type),
getType(node),
constant(utf8Slice(node.getValue()), VARCHAR));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,13 @@ public MethodHandle resolveOperator(OperatorType operatorType, List<? extends Ty
return functionRegistry.getScalarFunctionImplementation(functionRegistry.resolveOperator(operatorType, argumentTypes)).getMethodHandle();
}

@Override
public MethodHandle resolveConstructor(Type type)
{
checkState(functionRegistry != null, "functionRegistry was not set");
return functionRegistry.getScalarFunctionImplementation(functionRegistry.resolveConstructor(type)).getMethodHandle();
}

public static class TypeCompatibility
{
private final Optional<Type> commonSuperType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,20 @@
import static com.facebook.presto.spi.type.VarcharType.VARCHAR;
import static com.facebook.presto.spi.type.VarcharType.createUnboundedVarcharType;
import static com.facebook.presto.spi.type.VarcharType.createVarcharType;
import static com.facebook.presto.type.ColorType.COLOR;
import static com.facebook.presto.type.IpAddressType.IPADDRESS;
import static com.facebook.presto.type.JoniRegexpType.JONI_REGEXP;
import static com.facebook.presto.type.JsonPathType.JSON_PATH;
import static com.facebook.presto.type.JsonType.JSON;
import static com.facebook.presto.type.LikePatternType.LIKE_PATTERN;
import static com.facebook.presto.type.Re2JRegexpType.RE2J_REGEXP;
import static com.facebook.presto.type.UnknownType.UNKNOWN;
import static com.google.common.io.BaseEncoding.base16;
import static io.airlift.slice.Slices.utf8Slice;
import static io.airlift.slice.Slices.wrappedBuffer;
import static java.lang.String.format;
import static java.util.Objects.requireNonNull;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
Expand All @@ -86,6 +93,29 @@ public void testNonexistentType()
}
}

@Test
public void testResolveConstructor()
throws Throwable
{
assertEquals(
typeRegistry.resolveConstructor(BIGINT)
.invoke(utf8Slice("123")),
123L);

assertEquals(
typeRegistry.resolveConstructor(IPADDRESS)
.invoke(utf8Slice("1.2.3.4")),
wrappedBuffer(base16().decode("00000000000000000000FFFF01020304")));

assertEquals(
typeRegistry.resolveConstructor(JSON)
.invoke(utf8Slice("{ \"abc\": 123 }")),
utf8Slice("{\"abc\":123}"));

assertThatThrownBy(() -> typeRegistry.resolveConstructor(COLOR))
.hasMessageMatching("CAST to color cannot be applied to varchar");
}

@Test
public void testIsTypeOnlyCoercion()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public enum OperatorType
GREATER_THAN_OR_EQUAL(">="),
BETWEEN("BETWEEN"),
CAST("CAST"),
CONSTRUCT("CONSTRUCT"),
SUBSCRIPT("[]"),
HASH_CODE("HASH CODE"),
SATURATED_FLOOR_CAST("SATURATED FLOOR CAST"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,6 @@ public interface TypeManager
Optional<Type> coerceTypeBase(Type sourceType, String resultTypeBase);

MethodHandle resolveOperator(OperatorType operatorType, List<? extends Type> argumentTypes);

MethodHandle resolveConstructor(Type type);
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,10 @@ public MethodHandle resolveOperator(OperatorType operatorType, List<? extends Ty
{
throw new UnsupportedOperationException();
}

@Override
public MethodHandle resolveConstructor(Type type)
{
throw new UnsupportedOperationException();
}
}