diff --git a/presto-hive/src/main/java/com/facebook/presto/hive/HiveMetadata.java b/presto-hive/src/main/java/com/facebook/presto/hive/HiveMetadata.java index 63af4b156de8..9c0ab370db50 100644 --- a/presto-hive/src/main/java/com/facebook/presto/hive/HiveMetadata.java +++ b/presto-hive/src/main/java/com/facebook/presto/hive/HiveMetadata.java @@ -174,6 +174,7 @@ import static com.facebook.presto.hive.HiveType.HIVE_STRING; import static com.facebook.presto.hive.HiveType.toHiveType; import static com.facebook.presto.hive.HiveUtil.PRESTO_VIEW_FLAG; +import static com.facebook.presto.hive.HiveUtil.assignFieldNamesForAnonymousRowColumns; import static com.facebook.presto.hive.HiveUtil.columnExtraInfo; import static com.facebook.presto.hive.HiveUtil.decodeViewData; import static com.facebook.presto.hive.HiveUtil.encodeViewData; @@ -749,7 +750,12 @@ public ConnectorTableHandle createTemporaryTable(ConnectorSession session, List< return new HiveBucketProperty(partitioning.getPartitionColumns(), partitioningHandle.getBucketCount(), ImmutableList.of()); }); - List columnHandles = getColumnHandles(columns, ImmutableSet.of(), typeTranslator); + List columnHandles = getColumnHandles( + // Hive doesn't support anonymous rows + // Since this method doesn't create a real table, it is fine to assign dummy field names to the anonymous rows + assignFieldNamesForAnonymousRowColumns(columns, typeManager), + ImmutableSet.of(), + typeTranslator); storageFormat.validateColumns(columnHandles); Table table = Table.builder() diff --git a/presto-hive/src/main/java/com/facebook/presto/hive/HiveUtil.java b/presto-hive/src/main/java/com/facebook/presto/hive/HiveUtil.java index 10f574b3e66e..c4b78d0ed7be 100644 --- a/presto-hive/src/main/java/com/facebook/presto/hive/HiveUtil.java +++ b/presto-hive/src/main/java/com/facebook/presto/hive/HiveUtil.java @@ -19,6 +19,7 @@ import com.facebook.presto.hive.metastore.Table; import com.facebook.presto.hive.util.FooterAwareRecordReader; import com.facebook.presto.orc.OrcReader; +import com.facebook.presto.spi.ColumnMetadata; import com.facebook.presto.spi.ConnectorTableHandle; import com.facebook.presto.spi.ErrorCodeSupplier; import com.facebook.presto.spi.PrestoException; @@ -28,8 +29,13 @@ import com.facebook.presto.spi.type.CharType; import com.facebook.presto.spi.type.DecimalType; import com.facebook.presto.spi.type.Decimals; +import com.facebook.presto.spi.type.NamedTypeSignature; +import com.facebook.presto.spi.type.RowFieldName; 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.facebook.presto.spi.type.VarcharType; import com.google.common.base.Joiner; import com.google.common.base.Splitter; @@ -1060,4 +1066,62 @@ private static Map buildPhysicalNameOrdinalMap(OrcReader reader return physicalNameOrdinalMap.build(); } + + public static List assignFieldNamesForAnonymousRowColumns(List columns, TypeManager typeManager) + { + return columns.stream() + .map(column -> new ColumnMetadata( + column.getName(), + typeManager.getType(assignFieldNamesForAnonymousRowType(column.getType().getTypeSignature())), + column.isNullable(), + column.getComment(), + column.getExtraInfo(), + column.isHidden(), + column.getProperties())) + .collect(toImmutableList()); + } + + private static TypeSignature assignFieldNamesForAnonymousRowType(TypeSignature typeSignature) + { + List parameters = typeSignature.getParameters(); + + if (typeSignature.getBase().equals(StandardTypes.ROW)) { + ImmutableList.Builder updatedParameters = ImmutableList.builder(); + for (int i = 0; i < parameters.size(); i++) { + TypeSignatureParameter typeSignatureParameter = parameters.get(i); + checkArgument(typeSignatureParameter.isNamedTypeSignature(), "unexpected row type signature parameter: %s", typeSignatureParameter); + NamedTypeSignature namedTypeSignature = typeSignatureParameter.getNamedTypeSignature(); + updatedParameters.add(TypeSignatureParameter.of(new NamedTypeSignature( + Optional.of(namedTypeSignature.getFieldName().orElse(new RowFieldName("_field_" + i, false))), + assignFieldNamesForAnonymousRowType(namedTypeSignature.getTypeSignature())))); + } + return new TypeSignature(StandardTypes.ROW, updatedParameters.build()); + } + + if (!parameters.isEmpty()) { + ImmutableList.Builder updatedParameters = ImmutableList.builder(); + for (TypeSignatureParameter parameter : parameters) { + switch (parameter.getKind()) { + case LONG: + case VARIABLE: + updatedParameters.add(parameter); + continue; + case TYPE: + updatedParameters.add(TypeSignatureParameter.of(assignFieldNamesForAnonymousRowType(parameter.getTypeSignature()))); + break; + case NAMED_TYPE: + NamedTypeSignature namedTypeSignature = parameter.getNamedTypeSignature(); + updatedParameters.add(TypeSignatureParameter.of(new NamedTypeSignature( + namedTypeSignature.getFieldName(), + assignFieldNamesForAnonymousRowType(namedTypeSignature.getTypeSignature())))); + break; + default: + throw new IllegalArgumentException("Unexpected parameter type: " + parameter.getKind()); + } + } + return new TypeSignature(typeSignature.getBase(), updatedParameters.build()); + } + + return typeSignature; + } } diff --git a/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestAggregations.java b/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestAggregations.java index 79dc42d2b7ce..9ad7a2181f5d 100644 --- a/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestAggregations.java +++ b/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestAggregations.java @@ -1338,4 +1338,17 @@ public void testQuantileDigestMergeGroupBy() "GROUP BY partkey", "SELECT partkey, true FROM lineitem GROUP BY partkey"); } + + @Test + public void testGroupedRow() + { + assertQuery( + "SELECT count(r[1]), count(r[2]) " + + "FROM (" + + " SELECT orderkey, max_by(ROW(orderstatus, shippriority), orderstatus) AS r " + + " FROM orders " + + " GROUP BY orderkey" + + ")", + "SELECT 15000, 15000"); + } }