@VisibleForTesting
    static Function<HiveColumnHandle, ColumnMetadata> columnMetadataGetter(Table table, TypeManager typeManager, ColumnConverter columnConverter, List<String> notNullColumns)
    {
        ImmutableList.Builder<String> columnNames = ImmutableList.builder();
        table.getPartitionColumns().stream().map(Column::getName).forEach(columnNames::add);
        table.getDataColumns().stream().map(Column::getName).forEach(columnNames::add);
        List<String> allColumnNames = columnNames.build();
        if (allColumnNames.size() > Sets.newHashSet(allColumnNames).size()) {
            throw new PrestoException(HIVE_INVALID_METADATA,
                    format("Hive metadata for table %s is invalid: Table descriptor contains duplicate columns", table.getTableName()));
        }

        List<Column> tableColumns = table.getDataColumns();
        ImmutableMap.Builder<String, Optional<String>> builder = ImmutableMap.builder();
        ImmutableMap.Builder<String, Optional<String>> typeMetadataBuilder = ImmutableMap.builder();

        for (Column field : concat(tableColumns, table.getPartitionColumns())) {
            if (field.getComment().isPresent() && !field.getComment().get().equals("from deserializer")) {
                builder.put(field.getName(), field.getComment());
            }
            else {
                builder.put(field.getName(), Optional.empty());
            }
            typeMetadataBuilder.put(field.getName(), field.getTypeMetadata());
        }
        // add hidden columns
        builder.put(PATH_COLUMN_NAME, Optional.empty());
        if (table.getStorage().getBucketProperty().isPresent()) {
            builder.put(BUCKET_COLUMN_NAME, Optional.empty());
        }

        builder.put(FILE_SIZE_COLUMN_NAME, Optional.empty());
        builder.put(FILE_MODIFIED_TIME_COLUMN_NAME, Optional.empty());
        builder.put(ROW_ID_COLUMN_NAME, Optional.empty());

        Map<String, Optional<String>> columnComment = builder.build();

        Map<String, Optional<String>> typeMetadata = typeMetadataBuilder.build();

        return handle -> new ColumnMetadata(
                handle.getName(),
                typeManager.getType(columnConverter.getTypeSignature(handle.getHiveType(), typeMetadata.getOrDefault(handle.getName(), Optional.empty()))),
                !notNullColumns.contains(handle.getName()),
                columnComment.get(handle.getName()).orElse(null),
                columnExtraInfo(handle.isPartitionKey()),
                handle.isHidden(),
                ImmutableMap.of());
    }
@Test
    public void testColumnMetadataGetter()
    {
        TypeManager mockTypeManager = new TestingTypeManager();
        Column column1 = new Column("c1", HIVE_INT, Optional.empty(), Optional.of("some-metadata"));
        HiveColumnHandle hiveColumnHandle1 = new HiveColumnHandle(
                column1.getName(),
                HiveType.HIVE_INT,
                TypeSignature.parseTypeSignature("int"),
                0,
                HiveColumnHandle.ColumnType.REGULAR,
                Optional.empty(),
                Optional.empty());
        HiveColumnHandle hidden = new HiveColumnHandle(
                HiveColumnHandle.PATH_COLUMN_NAME,
                HiveType.HIVE_INT,
                TypeSignature.parseTypeSignature("int"),
                0,
                HiveColumnHandle.ColumnType.SYNTHESIZED,
                Optional.empty(),
                Optional.empty());
        Column partitionColumn = new Column("ds", HIVE_STRING, Optional.empty(), Optional.empty());
        Table mockTable = new Table(
                "schema",
                "table",
                "user",
                PrestoTableType.MANAGED_TABLE,
                new Storage(fromHiveStorageFormat(ORC),
                        "location",
                        Optional.of(new HiveBucketProperty(
                                ImmutableList.of(column1.getName()),
                                100,
                                ImmutableList.of(),
                                HIVE_COMPATIBLE,
                                Optional.empty())),
                        false,
                        ImmutableMap.of(),
                        ImmutableMap.of()),
                ImmutableList.of(column1),
                ImmutableList.of(partitionColumn),
                ImmutableMap.of(),
                Optional.empty(),
                Optional.empty());

        ColumnMetadata actual = HiveMetadata.columnMetadataGetter(mockTable, mockTypeManager, new HiveColumnConverter(), ImmutableList.of()).apply(hiveColumnHandle1);
        ColumnMetadata expected = new ColumnMetadata("c1", IntegerType.INTEGER);
        assertEquals(actual, expected);

        actual = HiveMetadata.columnMetadataGetter(mockTable, mockTypeManager, new TestColumnConverter(), ImmutableList.of()).apply(hidden);
        expected = ColumnMetadata.builder().setName(HiveColumnHandle.PATH_COLUMN_NAME).setType(IntegerType.INTEGER).setHidden(true).build();
        assertEquals(actual, expected);
    }