All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.netflix.metacat.converters.impl.MapStructHiveConverters Maven / Gradle / Ivy

There is a newer version: 0.1.53
Show newest version
/*
 * Copyright 2016 Netflix, Inc.
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *        http://www.apache.org/licenses/LICENSE-2.0
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.netflix.metacat.converters.impl;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.netflix.metacat.common.QualifiedName;
import com.netflix.metacat.common.dto.AuditDto;
import com.netflix.metacat.common.dto.DatabaseDto;
import com.netflix.metacat.common.dto.FieldDto;
import com.netflix.metacat.common.dto.PartitionDto;
import com.netflix.metacat.common.dto.StorageDto;
import com.netflix.metacat.common.dto.TableDto;
import com.netflix.metacat.converters.HiveConverters;
import org.apache.hadoop.hive.metastore.Warehouse;
import org.apache.hadoop.hive.metastore.api.Database;
import org.apache.hadoop.hive.metastore.api.FieldSchema;
import org.apache.hadoop.hive.metastore.api.MetaException;
import org.apache.hadoop.hive.metastore.api.Partition;
import org.apache.hadoop.hive.metastore.api.SerDeInfo;
import org.apache.hadoop.hive.metastore.api.StorageDescriptor;
import org.apache.hadoop.hive.metastore.api.Table;
import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;

import java.time.Instant;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static java.util.Collections.EMPTY_MAP;

@Mapper(uses = DateConverters.class,
        unmappedTargetPolicy = ReportingPolicy.ERROR,
        componentModel = "default")
public abstract class MapStructHiveConverters implements HiveConverters {
    private static final Splitter SLASH_SPLITTER = Splitter.on('/');
    private static final Splitter EQUAL_SPLITTER = Splitter.on('=').limit(2);

    @VisibleForTesting
    Integer dateToEpochSeconds(Date date) {
        if (date == null) {
            return null;
        }

        Instant instant = date.toInstant();
        long seconds = instant.getEpochSecond();
        if (seconds <= Integer.MAX_VALUE) {
            return (int) seconds;
        }

        throw new IllegalStateException("Unable to convert date " + date + " to an integer seconds value");
    }

    private Date epochSecondsToDate(long seconds) {
        Instant instant = Instant.ofEpochSecond(seconds);
        return Date.from(instant);
    }

    private FieldDto hiveToMetacatField(FieldSchema field, boolean isPartitionKey) {
        FieldDto dto = new FieldDto();
        dto.setName(field.getName());
        dto.setType(field.getType());
        dto.setSource_type(field.getType());
        dto.setComment(field.getComment());
        dto.setPartition_key(isPartitionKey);

        return dto;
    }

    private FieldSchema metacatToHiveField(FieldDto fieldDto) {
        FieldSchema result = new FieldSchema();
        result.setName(fieldDto.getName());
        result.setType(fieldDto.getType());
        result.setComment(fieldDto.getComment());
        return result;
    }

    @Override
    public TableDto hiveToMetacatTable(QualifiedName name, Table table) {
        TableDto dto = new TableDto();
        dto.setSerde(toStorageDto(table.getSd(), table.getOwner()));
        dto.setAudit(new AuditDto());
        dto.setName(name);
        if (table.isSetCreateTime()) {
            dto.getAudit().setCreatedDate(epochSecondsToDate(table.getCreateTime()));
        }
        dto.setMetadata(table.getParameters());

        List nonPartitionColumns = table.getSd().getCols();
        List partitionColumns = table.getPartitionKeys();
        List allFields = Lists.newArrayListWithCapacity(nonPartitionColumns.size() + partitionColumns.size());
        nonPartitionColumns.stream()
                           .map(field -> this.hiveToMetacatField(field, false))
                           .forEachOrdered(allFields::add);
        partitionColumns.stream()
                        .map(field -> this.hiveToMetacatField(field, true))
                        .forEachOrdered(allFields::add);
        dto.setFields(allFields);

        return dto;
    }

    @Override
    @SuppressWarnings("unchecked")
    public Database metacatToHiveDatabase(DatabaseDto dto) {
        Database database = new Database();

        String name = "";
        String description = "";
        QualifiedName databaseName = dto.getName();
        if (databaseName != null) {
            name = databaseName.getDatabaseName();
            // Since this is required setting it to the same as the DB name for now
            description = databaseName.getDatabaseName();
        }
        database.setName(name);
        database.setDescription(description);

        String dbUri = dto.getUri();
        if (Strings.isNullOrEmpty(dbUri)) {
            dbUri = "";
        }
        database.setLocationUri(dbUri);

        Map metadata = dto.getMetadata();
        if (metadata == null) {
            metadata = EMPTY_MAP;
        }
        database.setParameters(metadata);

        return database;
    }

    @Override
    public Table metacatToHiveTable(TableDto dto) {
        Table table = new Table();
        String tableName = "";
        String databaseName = "";

        QualifiedName name = dto.getName();
        if (name != null) {
            tableName = name.getTableName();
            databaseName = name.getDatabaseName();
        }
        table.setTableName(tableName);
        table.setDbName(databaseName);

        StorageDto storageDto = dto.getSerde();
        String owner = "";
        if (storageDto != null && storageDto.getOwner() != null) {
            owner = storageDto.getOwner();
        }
        table.setOwner(owner);

        AuditDto auditDto = dto.getAudit();
        if (auditDto != null && auditDto.getCreatedDate() != null) {
            table.setCreateTime(dateToEpochSeconds(auditDto.getCreatedDate()));
        }

        Map params = Collections.emptyMap();
        if (dto.getMetadata() != null) {
            params = dto.getMetadata();
        }
        table.setParameters(params);

        // TODO get this
        table.setTableType("EXTERNAL_TABLE");

        table.setSd(fromStorageDto(storageDto));
        StorageDescriptor sd = table.getSd();

        List fields = dto.getFields();
        if (fields == null) {
            table.setPartitionKeys(Collections.emptyList());
            sd.setCols(Collections.emptyList());
        } else {
            List nonPartitionFields = Lists.newArrayListWithCapacity(fields.size());
            List partitionFields = Lists.newArrayListWithCapacity(fields.size());
            for (FieldDto fieldDto : fields) {
                FieldSchema f = metacatToHiveField(fieldDto);

                if (fieldDto.isPartition_key()) {
                    partitionFields.add(f);
                } else {
                    nonPartitionFields.add(f);
                }
            }
            table.setPartitionKeys(partitionFields);
            sd.setCols(nonPartitionFields);
        }

        return table;
    }

    private StorageDto toStorageDto(StorageDescriptor sd, String owner) {
        StorageDto result = new StorageDto();
        if (sd != null) {
            result.setOwner(owner);
            result.setUri(sd.getLocation());
            result.setInputFormat(sd.getInputFormat());
            result.setOutputFormat(sd.getOutputFormat());
            result.setParameters(sd.getParameters());
            SerDeInfo serde = sd.getSerdeInfo();
            if (serde != null) {
                result.setSerializationLib(serde.getSerializationLib());
                result.setSerdeInfoParameters(serde.getParameters());
            }
        }
        return result;
    }

    private StorageDescriptor fromStorageDto(StorageDto storageDto) {
        // Set all required fields to a non-null value
        StorageDescriptor result = new StorageDescriptor();
        String inputFormat = "";
        String location = "";
        String outputFormat = "";
        String serdeName = "";
        String serializationLib = "";
        Map sdParams = EMPTY_MAP;
        Map serdeParams = EMPTY_MAP;

        if (storageDto != null) {
            if (storageDto.getInputFormat() != null) {
                inputFormat = storageDto.getInputFormat();
            }
            if (storageDto.getUri() != null) {
                location = storageDto.getUri();
            }
            if (storageDto.getOutputFormat() != null) {
                outputFormat = storageDto.getOutputFormat();
            }
            if (storageDto.getSerializationLib() != null) {
                serializationLib = storageDto.getSerializationLib();
            }
            if (storageDto.getParameters() != null) {
                sdParams = storageDto.getParameters();
            }
            if (storageDto.getSerdeInfoParameters() != null) {
                serdeParams = storageDto.getSerdeInfoParameters();
            }
        }

        result.setInputFormat(inputFormat);
        result.setLocation(location);
        result.setOutputFormat(outputFormat);
        result.setSerdeInfo(new SerDeInfo(serdeName, serializationLib, serdeParams));
        result.setCols(Collections.emptyList());
        result.setBucketCols(Collections.emptyList());
        result.setSortCols(Collections.emptyList());
        result.setParameters(sdParams);
        return result;
    }

    @Override
    public PartitionDto hiveToMetacatPartition(TableDto tableDto, Partition partition) {
        QualifiedName tableName = tableDto.getName();
        QualifiedName partitionName = QualifiedName.ofPartition(tableName.getCatalogName(), tableName.getDatabaseName(),
                tableName.getTableName(), getNameFromPartVals(tableDto, partition.getValues()));

        PartitionDto result = new PartitionDto();
        String owner = "";
        if (tableDto.getSerde() != null) {
            owner = tableDto.getSerde().getOwner();
        }
        result.setSerde(toStorageDto(partition.getSd(), owner));
        result.setMetadata(partition.getParameters());

        AuditDto auditDto = new AuditDto();
        auditDto.setCreatedDate(epochSecondsToDate(partition.getCreateTime()));
        auditDto.setLastModifiedDate(epochSecondsToDate(partition.getLastAccessTime()));
        result.setAudit(auditDto);
        result.setName(partitionName);
        return result;
    }

    @Override
    public List getPartValsFromName(TableDto tableDto, String partName) {
        // Unescape the partition name

        LinkedHashMap hm = null;
        try {
            hm = Warehouse.makeSpecFromName(partName);
        } catch (MetaException e) {
            throw new IllegalArgumentException("Invalid partition name", e);
        }

        List partVals = Lists.newArrayList();
        for (String key : tableDto.getPartition_keys()) {
            String val = hm.get(key);
            if (val == null) {
                throw new IllegalArgumentException("Invalid partition name - missing " + key);
            }
            partVals.add(val);
        }
        return partVals;
    }

    @Override
    public String getNameFromPartVals(TableDto tableDto, List partVals) {
        List partitionKeys = tableDto.getPartition_keys();
        if (partitionKeys.size() != partVals.size()) {
            throw new IllegalArgumentException("Not the same number of partition columns and partition values");
        }

        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < partitionKeys.size(); i++) {
            if (builder.length() > 0) {
                builder.append('/');
            }

            builder.append(partitionKeys.get(i));
            builder.append('=');
            builder.append(partVals.get(i));
        }
        return builder.toString();
    }

    @Override
    public Partition metacatToHivePartition(PartitionDto partitionDto, TableDto tableDto) {
        Partition result = new Partition();

        QualifiedName name = partitionDto.getName();
        List values = Lists.newArrayListWithCapacity(16);
        String databaseName = "";
        String tableName = "";
        if (name != null) {
            if (name.getPartitionName() != null) {
                for (String partialPartName : SLASH_SPLITTER.split(partitionDto.getName().getPartitionName())) {
                    List nameValues = ImmutableList.copyOf(EQUAL_SPLITTER.split(partialPartName));
                    if (nameValues.size() != 2) {
                        throw new IllegalStateException("Unrecognized partition name: " + partitionDto.getName());
                    }
                    String value = nameValues.get(1);
                    values.add(value);
                }
            }

            if (name.getDatabaseName() != null) {
                databaseName = name.getDatabaseName();
            }

            if (name.getTableName() != null) {
                tableName = name.getTableName();
            }
        }
        result.setValues(values);
        result.setDbName(databaseName);
        result.setTableName(tableName);

        Map metadata = partitionDto.getMetadata();
        if (metadata == null) {
            metadata = EMPTY_MAP;
        }
        result.setParameters(metadata);

        result.setSd(fromStorageDto(partitionDto.getSerde()));
        StorageDescriptor sd = result.getSd();
        if (tableDto != null) {
            if (sd.getSerdeInfo() != null && tableDto.getSerde() != null && Strings.isNullOrEmpty(
                    sd.getSerdeInfo().getSerializationLib())) {
                sd.getSerdeInfo().setSerializationLib(tableDto.getSerde().getSerializationLib());
            }

            List fields = tableDto.getFields();
            if (fields == null) {
                sd.setCols(Collections.emptyList());
            } else {
                sd.setCols(fields.stream()
                                 .filter(field -> !field.isPartition_key())
                                 .map(this::metacatToHiveField)
                                 .collect(Collectors.toList()));
            }
        }

        AuditDto auditDto = partitionDto.getAudit();
        if (auditDto != null) {
            if (auditDto.getCreatedDate() != null) {
                result.setCreateTime(dateToEpochSeconds(auditDto.getCreatedDate()));
            }
            if (auditDto.getLastModifiedDate() != null) {
                result.setLastAccessTime(dateToEpochSeconds(auditDto.getLastModifiedDate()));
            }
        }

        return result;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy