Skip to content

Commit

Permalink
Update ROW type to use generalized parameters
Browse files Browse the repository at this point in the history
Remove the "literal parameters" abstraction and update ROW type
to the new generalyzed type parameter abstraction.
  • Loading branch information
pnowojski authored and martint committed Jan 8, 2016
1 parent a633f0a commit d7738ba
Show file tree
Hide file tree
Showing 31 changed files with 595 additions and 263 deletions.
Expand Up @@ -13,6 +13,7 @@
*/
package com.facebook.presto.client;

import com.facebook.presto.spi.type.NamedTypeSignature;
import com.facebook.presto.spi.type.StandardTypes;
import com.facebook.presto.spi.type.TypeSignature;
import com.fasterxml.jackson.annotation.JsonCreator;
Expand All @@ -26,8 +27,10 @@
import java.util.Locale;
import java.util.Objects;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.google.common.base.Preconditions.checkArgument;
import static java.lang.String.format;
import static java.util.Collections.unmodifiableList;

@Immutable
Expand All @@ -36,33 +39,25 @@ public class ClientTypeSignature
private static final Pattern PATTERN = Pattern.compile(".*[<>,].*");
private final String rawType;
private final List<ClientTypeSignatureParameter> typeArguments;
private final List<Object> literalArguments;

public ClientTypeSignature(TypeSignature typeSignature)
{
this(
typeSignature.getBase(),
Lists.transform(typeSignature.getParameters(), ClientTypeSignatureParameter::new),
typeSignature.getLiteralParameters());
Lists.transform(typeSignature.getParameters(), ClientTypeSignatureParameter::new));
}

@JsonCreator
public ClientTypeSignature(
@JsonProperty("rawType") String rawType,
@JsonProperty("typeArguments") List<ClientTypeSignatureParameter> typeArguments,
@JsonProperty("literalArguments") List<Object> literalArguments)
@JsonProperty("typeArguments") List<ClientTypeSignatureParameter> typeArguments)
{
checkArgument(rawType != null, "rawType is null");
this.rawType = rawType;
checkArgument(!rawType.isEmpty(), "rawType is empty");
checkArgument(!PATTERN.matcher(rawType).matches(), "Bad characters in rawType type: %s", rawType);
checkArgument(typeArguments != null, "typeArguments is null");
checkArgument(literalArguments != null, "literalArguments is null");
for (Object literal : literalArguments) {
checkArgument(literal instanceof String || literal instanceof Long, "Unsupported literal type: %s", literal.getClass());
}
this.typeArguments = unmodifiableList(new ArrayList<>(typeArguments));
this.literalArguments = unmodifiableList(new ArrayList<>(literalArguments));
}

@JsonProperty
Expand All @@ -77,63 +72,46 @@ public List<ClientTypeSignatureParameter> getTypeArguments()
return typeArguments;
}

@JsonProperty
public List<Object> getLiteralArguments()
{
return literalArguments;
}

@Override
public String toString()
{
if (rawType.equals(StandardTypes.ROW)) {
return rowToString();
}
else {
return toString("(", ")");
StringBuilder typeName = new StringBuilder(rawType);
if (!typeArguments.isEmpty()) {
typeName.append("(");
boolean first = true;
for (ClientTypeSignatureParameter argument : typeArguments) {
if (!first) {
typeName.append(",");
}
first = false;
typeName.append(argument.toString());
}
typeName.append(")");
}
return typeName.toString();
}
}

@Deprecated
private String rowToString()
{
return toString("<", ">");
}

private String toString(String leftParameterBracket, String rightParameterBracket)
{
StringBuilder typeName = new StringBuilder(rawType);
if (!typeArguments.isEmpty()) {
typeName.append(leftParameterBracket);
boolean first = true;
for (ClientTypeSignatureParameter argument : typeArguments) {
if (!first) {
typeName.append(",");
}
first = false;
typeName.append(argument.toString());
}
typeName.append(rightParameterBracket);
}
if (!literalArguments.isEmpty()) {
typeName.append("(");
boolean first = true;
for (Object parameter : literalArguments) {
if (!first) {
typeName.append(",");
}
first = false;
if (parameter instanceof String) {
typeName.append("'").append(parameter).append("'");
}
else {
typeName.append(parameter.toString());
}
}
typeName.append(")");
}

return typeName.toString();
String types = typeArguments.stream()
.map(ClientTypeSignatureParameter::getNamedTypeSignature)
.map(NamedTypeSignature::getTypeSignature)
.map(TypeSignature::toString)
.collect(Collectors.joining(","));

String fieldNames = typeArguments.stream()
.map(ClientTypeSignatureParameter::getNamedTypeSignature)
.map(NamedTypeSignature::getName)
.map(name -> format("'%s'", name))
.collect(Collectors.joining(","));

return format("row<%s>(%s)", types, fieldNames);
}

@Override
Expand All @@ -149,13 +127,12 @@ public boolean equals(Object o)
ClientTypeSignature other = (ClientTypeSignature) o;

return Objects.equals(this.rawType.toLowerCase(Locale.ENGLISH), other.rawType.toLowerCase(Locale.ENGLISH)) &&
Objects.equals(this.typeArguments, other.typeArguments) &&
Objects.equals(this.literalArguments, other.literalArguments);
Objects.equals(this.typeArguments, other.typeArguments);
}

@Override
public int hashCode()
{
return Objects.hash(rawType.toLowerCase(Locale.ENGLISH), typeArguments, literalArguments);
return Objects.hash(rawType.toLowerCase(Locale.ENGLISH), typeArguments);
}
}
Expand Up @@ -13,6 +13,7 @@
*/
package com.facebook.presto.client;

import com.facebook.presto.spi.type.NamedTypeSignature;
import com.facebook.presto.spi.type.ParameterKind;
import com.facebook.presto.spi.type.TypeSignatureParameter;
import com.fasterxml.jackson.annotation.JsonCreator;
Expand Down Expand Up @@ -40,6 +41,8 @@ public ClientTypeSignatureParameter(TypeSignatureParameter typeParameterSignatur
case LONG_LITERAL:
value = typeParameterSignature.getLongLiteral();
break;
case NAMED_TYPE_SIGNATURE:
value = typeParameterSignature.getNamedTypeSignature();
default:
throw new UnsupportedOperationException(format("Unknown kind [%s]", kind));
}
Expand Down Expand Up @@ -84,6 +87,11 @@ public Long getLongLiteral()
return getValue(ParameterKind.LONG_LITERAL, Long.class);
}

public NamedTypeSignature getNamedTypeSignature()
{
return getValue(ParameterKind.NAMED_TYPE_SIGNATURE, NamedTypeSignature.class);
}

@Override
public String toString()
{
Expand Down
Expand Up @@ -13,7 +13,10 @@
*/
package com.facebook.presto.client;

import com.facebook.presto.spi.type.NamedTypeSignature;
import com.facebook.presto.spi.type.ParameterKind;
import com.facebook.presto.spi.type.TypeSignature;
import com.facebook.presto.spi.type.TypeSignatureParameter;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.ImmutableList;
Expand Down Expand Up @@ -240,10 +243,16 @@ private static Object fixValue(String type, Object value)
if (signature.getBase().equals(ROW)) {
Map<String, Object> fixedValue = new LinkedHashMap<>();
List<Object> listValue = List.class.cast(value);
checkArgument(listValue.size() == signature.getLiteralParameters().size(), "Mismatched data values and row type");
checkArgument(listValue.size() == signature.getParameters().size(), "Mismatched data values and row type");
for (int i = 0; i < listValue.size(); i++) {
String key = (String) signature.getLiteralParameters().get(i);
fixedValue.put(key, fixValue(signature.getTypeParametersAsTypeSignatures().get(i).toString(), listValue.get(i)));
TypeSignatureParameter parameter = signature.getParameters().get(i);
checkArgument(
parameter.getKind() == ParameterKind.NAMED_TYPE_SIGNATURE,
"Unexpected parameter [%s] for row type",
parameter);
NamedTypeSignature namedTypeSignature = parameter.getNamedTypeSignature();
String key = namedTypeSignature.getName();
fixedValue.put(key, fixValue(namedTypeSignature.getTypeSignature().toString(), listValue.get(i)));
}
return fixedValue;
}
Expand Down
25 changes: 18 additions & 7 deletions presto-hive/src/main/java/com/facebook/presto/hive/HiveType.java
Expand Up @@ -14,10 +14,12 @@
package com.facebook.presto.hive;

import com.facebook.presto.spi.PrestoException;
import com.facebook.presto.spi.type.NamedTypeSignature;
import com.facebook.presto.spi.type.StandardTypes;
import com.facebook.presto.spi.type.Type;
import com.facebook.presto.spi.type.TypeManager;
import com.facebook.presto.spi.type.TypeSignature;
import com.facebook.presto.spi.type.TypeSignatureParameter;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import com.google.common.collect.ImmutableList;
Expand Down Expand Up @@ -234,10 +236,16 @@ private static TypeInfo toTypeInfo(Type type)
return getMapTypeInfo(keyType, valueType);
}
if (isRowType(type)) {
ImmutableList.Builder<String> fieldNames = ImmutableList.builder();
for (TypeSignatureParameter parameter : type.getTypeSignature().getParameters()) {
if (!parameter.isNamedTypeSignature()) {
throw new IllegalArgumentException(format("Expected all parameters to be named type, but got %s", parameter));
}
NamedTypeSignature namedTypeSignature = parameter.getNamedTypeSignature();
fieldNames.add(namedTypeSignature.getName());
}
return getStructTypeInfo(
type.getTypeSignature().getLiteralParameters().stream()
.map(String.class::cast)
.collect(toList()),
fieldNames.build(),
type.getTypeParameters().stream()
.map(HiveType::toTypeInfo)
.collect(toList()));
Expand All @@ -260,19 +268,22 @@ private static TypeSignature getTypeSignature(TypeInfo typeInfo)
MapTypeInfo mapTypeInfo = checkType(typeInfo, MapTypeInfo.class, "fieldInspector");
TypeSignature keyType = getTypeSignature(mapTypeInfo.getMapKeyTypeInfo());
TypeSignature valueType = getTypeSignature(mapTypeInfo.getMapValueTypeInfo());
return new TypeSignature(StandardTypes.MAP, ImmutableList.of(keyType, valueType), ImmutableList.of());
return new TypeSignature(
StandardTypes.MAP,
ImmutableList.of(TypeSignatureParameter.of(keyType), TypeSignatureParameter.of(valueType)));
case LIST:
ListTypeInfo listTypeInfo = checkType(typeInfo, ListTypeInfo.class, "fieldInspector");
TypeSignature elementType = getTypeSignature(listTypeInfo.getListElementTypeInfo());
return new TypeSignature(StandardTypes.ARRAY, ImmutableList.of(elementType), ImmutableList.of());
return new TypeSignature(
StandardTypes.ARRAY,
ImmutableList.of(TypeSignatureParameter.of(elementType)));
case STRUCT:
StructTypeInfo structTypeInfo = checkType(typeInfo, StructTypeInfo.class, "fieldInspector");
List<Object> fieldNames = ImmutableList.copyOf(structTypeInfo.getAllStructFieldNames());
List<TypeSignature> fieldTypes = structTypeInfo.getAllStructFieldTypeInfos()
.stream()
.map(HiveType::getTypeSignature)
.collect(toList());
return new TypeSignature(StandardTypes.ROW, fieldTypes, fieldNames);
return new TypeSignature(StandardTypes.ROW, fieldTypes, structTypeInfo.getAllStructFieldNames());
}
throw new PrestoException(NOT_SUPPORTED, format("Unsupported Hive type: %s", typeInfo));
}
Expand Down
Expand Up @@ -156,8 +156,8 @@ else if (isMapType(type)) {
}
else if (isRowType(type)) {
return ObjectInspectorFactory.getStandardStructObjectInspector(
type.getTypeSignature().getLiteralParameters().stream()
.map(String.class::cast)
type.getTypeSignature().getParameters().stream()
.map(parameter -> parameter.getNamedTypeSignature().getName())
.collect(toList()),
type.getTypeParameters().stream()
.map(HiveWriteUtils::getJavaObjectInspector)
Expand Down
Expand Up @@ -82,7 +82,7 @@ public Type getParameterizedType(String baseTypeName, List<TypeSignatureParamete
}

@Override
public Type getParameterizedType(String baseTypeName, List<TypeSignature> typeParameters, List<Object> literalParameters)
public Type getParameterizedType(String baseTypeName, List<TypeSignature> typeParameters, List<String> literalParameters)
{
return null;
}
Expand Down
Expand Up @@ -16,6 +16,7 @@
import com.facebook.presto.spi.type.Type;
import com.facebook.presto.spi.type.TypeManager;
import com.facebook.presto.spi.type.TypeSignature;
import com.facebook.presto.spi.type.TypeSignatureParameter;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Joiner;
Expand Down Expand Up @@ -292,11 +293,10 @@ private static boolean matchArguments(

private static boolean matchAndBind(Map<String, Type> boundParameters, Map<String, TypeParameterRequirement> typeParameters, TypeSignature parameter, Type type, boolean allowCoercion, TypeManager typeManager)
{
// TODO: add literals to Types and switch to TypeSignatureParameter so boundParameters map includes also literal parameter bindings
List<TypeSignature> typeSignatures = parameter.getTypeParametersAsTypeSignatures();
List<TypeSignatureParameter> parameters = parameter.getParameters();
// If this parameter is already bound, then match (with coercion)
if (boundParameters.containsKey(parameter.getBase())) {
checkArgument(typeSignatures.isEmpty(), "Unexpected parameteric type");
checkArgument(parameters.isEmpty(), "Unexpected parameteric type");
if (allowCoercion) {
if (canCoerce(type, boundParameters.get(parameter.getBase()))) {
return true;
Expand All @@ -314,13 +314,27 @@ else if (canCoerce(boundParameters.get(parameter.getBase()), type) && typeParame
}

// Recurse into component types
if (!typeSignatures.isEmpty()) {
if (type.getTypeParameters().size() != typeSignatures.size()) {
if (!parameters.isEmpty()) {
// TODO: add support for types with both literal and type parameters? Now for such types this check will fail
if (type.getTypeParameters().size() != parameters.size()) {
return false;
}
for (int i = 0; i < typeSignatures.size(); i++) {
for (int i = 0; i < parameters.size(); i++) {
Type componentType = type.getTypeParameters().get(i);
TypeSignature componentSignature = typeSignatures.get(i);
TypeSignatureParameter componentParameter = parameters.get(i);
TypeSignature componentSignature;
switch (componentParameter.getKind()) {
case TYPE_SIGNATURE:
componentSignature = componentParameter.getTypeSignature();
break;
case NAMED_TYPE_SIGNATURE:
componentSignature = componentParameter.getNamedTypeSignature().getTypeSignature();
break;
default:
// TODO: add support for types with both literal and type parameters?
return false;
}

if (!matchAndBind(boundParameters, typeParameters, componentSignature, componentType, allowCoercion, typeManager)) {
return false;
}
Expand All @@ -338,7 +352,7 @@ else if (canCoerce(boundParameters.get(parameter.getBase()), type) && typeParame
}

// We've already checked all the components, so just match the base type
if (!typeSignatures.isEmpty()) {
if (!parameters.isEmpty()) {
return type.getTypeSignature().getBase().equals(parameter.getBase());
}

Expand Down
Expand Up @@ -389,7 +389,7 @@ else if (queryInfo.getOutputStage() == null) {
exchangeClient.close();

// Return a single value for clients that require a result.
columns = ImmutableList.of(new Column("result", "boolean", new ClientTypeSignature(StandardTypes.BOOLEAN, ImmutableList.of(), ImmutableList.of())));
columns = ImmutableList.of(new Column("result", "boolean", new ClientTypeSignature(StandardTypes.BOOLEAN, ImmutableList.of())));
data = ImmutableSet.<List<Object>>of(ImmutableList.<Object>of(true));
}
}
Expand Down

0 comments on commit d7738ba

Please sign in to comment.