Skip to content
Merged
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 @@ -37,6 +37,7 @@
#include "velox/common/compression/Compression.h"
// clang-format on

#include <folly/String.h>
#include <folly/container/F14Set.h>

using namespace facebook::velox;
Expand Down Expand Up @@ -799,6 +800,56 @@ std::unique_ptr<common::Filter> toFilter(
VELOX_UNSUPPORTED("Unsupported filter found.");
}

template <TypeKind KIND>
TypePtr fieldNamesToLowerCase(const TypePtr& type) {
return type;
}

template <>
TypePtr fieldNamesToLowerCase<TypeKind::ARRAY>(const TypePtr& type);

template <>
TypePtr fieldNamesToLowerCase<TypeKind::MAP>(const TypePtr& type);

template <>
TypePtr fieldNamesToLowerCase<TypeKind::ROW>(const TypePtr& type);

template <>
TypePtr fieldNamesToLowerCase<TypeKind::ARRAY>(const TypePtr& type) {
auto& elementType = type->childAt(0);
return std::make_shared<ArrayType>(VELOX_DYNAMIC_TYPE_DISPATCH(
fieldNamesToLowerCase, elementType->kind(), elementType));
}

template <>
TypePtr fieldNamesToLowerCase<TypeKind::MAP>(const TypePtr& type) {
auto& keyType = type->childAt(0);
auto& valueType = type->childAt(1);
return std::make_shared<MapType>(
VELOX_DYNAMIC_TYPE_DISPATCH(
fieldNamesToLowerCase, keyType->kind(), keyType),
VELOX_DYNAMIC_TYPE_DISPATCH(
fieldNamesToLowerCase, valueType->kind(), valueType));
}

template <>
TypePtr fieldNamesToLowerCase<TypeKind::ROW>(const TypePtr& type) {
auto& rowType = type->asRow();
std::vector<std::string> names;
std::vector<TypePtr> types;
names.reserve(type->size());
types.reserve(type->size());
for (int i = 0; i < rowType.size(); i++) {
std::string name = rowType.nameOf(i);
folly::toLowerAscii(name);
names.push_back(std::move(name));
auto& childType = rowType.childAt(i);
types.push_back(VELOX_DYNAMIC_TYPE_DISPATCH(
fieldNamesToLowerCase, childType->kind(), childType));
}
return std::make_shared<RowType>(std::move(names), std::move(types));
}

std::shared_ptr<connector::ConnectorTableHandle> toConnectorTableHandle(
const protocol::TableHandle& tableHandle,
const VeloxExprConverter& exprConverter,
Expand Down Expand Up @@ -839,8 +890,15 @@ std::shared_ptr<connector::ConnectorTableHandle> toConnectorTableHandle(
names.reserve(hiveLayout->dataColumns.size());
types.reserve(hiveLayout->dataColumns.size());
for (auto& column : hiveLayout->dataColumns) {
names.push_back(column.name);
types.push_back(typeParser.parse(column.type));
std::string name = column.name;
folly::toLowerAscii(name);
names.emplace_back(std::move(name));
auto parsedType = typeParser.parse(column.type);
// The type from the metastore may have upper case letters
// in field names, convert them all to lower case to be
// compatible with Presto.
types.push_back(VELOX_DYNAMIC_TYPE_DISPATCH(
fieldNamesToLowerCase, parsedType->kind(), parsedType));
}
dataColumns = ROW(std::move(names), std::move(types));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,29 @@
package com.facebook.presto.nativeworker;

import com.facebook.presto.Session;
import com.facebook.presto.common.type.RowType;
import com.facebook.presto.spi.ColumnMetadata;
import com.facebook.presto.spi.ConnectorTableMetadata;
import com.facebook.presto.spi.SchemaTableName;
import com.facebook.presto.testing.QueryRunner;
import com.facebook.presto.tests.AbstractTestQueryFramework;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.testng.annotations.Test;

import java.util.Map;
import java.util.Optional;
import java.util.UUID;

import static com.facebook.presto.SystemSessionProperties.JOIN_DISTRIBUTION_TYPE;
import static com.facebook.presto.common.type.BigintType.BIGINT;
import static com.facebook.presto.common.type.VarcharType.VARCHAR;
import static com.facebook.presto.hive.HiveStorageFormat.DWRF;
import static com.facebook.presto.hive.HiveTableProperties.BUCKETED_BY_PROPERTY;
import static com.facebook.presto.hive.HiveTableProperties.BUCKET_COUNT_PROPERTY;
import static com.facebook.presto.hive.HiveTableProperties.PARTITIONED_BY_PROPERTY;
import static com.facebook.presto.hive.HiveTableProperties.SORTED_BY_PROPERTY;
import static com.facebook.presto.hive.HiveTableProperties.STORAGE_FORMAT_PROPERTY;
import static com.facebook.presto.nativeworker.NativeQueryRunnerUtils.createBucketedCustomer;
import static com.facebook.presto.nativeworker.NativeQueryRunnerUtils.createBucketedLineitemAndOrders;
import static com.facebook.presto.nativeworker.NativeQueryRunnerUtils.createCustomer;
Expand All @@ -45,6 +57,7 @@
import static com.facebook.presto.sql.planner.plan.ExchangeNode.Scope.REMOTE_STREAMING;
import static com.facebook.presto.sql.planner.plan.ExchangeNode.Type.GATHER;
import static com.facebook.presto.sql.planner.plan.ExchangeNode.Type.REPARTITION;
import static com.facebook.presto.transaction.TransactionBuilder.transaction;
import static java.lang.String.format;
import static org.testng.Assert.assertEquals;

Expand Down Expand Up @@ -1274,6 +1287,50 @@ public void testUnionAllInsert()
}
}

@Test
public void testSelectFieldsWithCapitalLetters()
{
Session session = Session.builder(getSession())
// This is needed for Spark.
.setCatalogSessionProperty("hive", "optimized_partition_update_serialization_enabled", "false")
.build();
String tmpTableName = generateRandomTableName();
try {
QueryRunner queryRunner = getQueryRunner();
// We have to create the table through metadata, rather than
// through Presto SQL since, if we use the latter, Presto will
// convert the field names to lower case.
SchemaTableName table = new SchemaTableName(session.getSchema().get(), tmpTableName);
Map<String, Object> tableProperties = ImmutableMap.<String, Object>builder()
.put(STORAGE_FORMAT_PROPERTY, DWRF)
.put(PARTITIONED_BY_PROPERTY, ImmutableList.of())
.put(BUCKETED_BY_PROPERTY, ImmutableList.of())
.put(BUCKET_COUNT_PROPERTY, 0)
.put(SORTED_BY_PROPERTY, ImmutableList.of())
.build();
ConnectorTableMetadata tableMetadata = new ConnectorTableMetadata(table, ImmutableList.of(
new ColumnMetadata("col", RowType.from(ImmutableList.of(
new RowType.Field(Optional.of("NationKey"), BIGINT),
new RowType.Field(Optional.of("NAME"), VARCHAR),
new RowType.Field(Optional.of("ReGiOnKeY"), BIGINT),
new RowType.Field(Optional.of("commenT"), VARCHAR))))),
tableProperties);
transaction(queryRunner.getTransactionManager(), queryRunner.getAccessControl())
.singleStatement()
.execute(session, s -> {
queryRunner.getMetadata().createTable(s, s.getCatalog().get(), tableMetadata, false);
});

// Write some data so we can read it back.
queryRunner.execute(session, String.format("INSERT INTO %s SELECT cast(row(nationkey, name, regionkey, comment) as row(nationkey bigint, name varchar, regionkey bigint, comment varchar)) FROM nation", tmpTableName));
// This should work since Presto is case insensitive.
assertQuery(String.format("SELECT col.nationkey, col.name, col.regionkey, col.comment FROM %s", tmpTableName), "SELECT nationkey, name, regionkey, comment FROM nation");
}
finally {
dropTableIfExists(tmpTableName);
}
}

private void assertQueryResultCount(String sql, int expectedResultCount)
{
assertEquals(getQueryRunner().execute(sql).getRowCount(), expectedResultCount);
Expand Down