Search in sources :

Example 6 with ConnectorMaterializedViewDefinition

use of com.facebook.presto.spi.ConnectorMaterializedViewDefinition in project presto by prestodb.

the class HiveMaterializedViewUtils method validateMaterializedViewPartitionColumns.

/**
 * Validate the partition columns of a materialized view to ensure 1) a materialized view is partitioned; 2) it has at least one partition
 * directly mapped to all base tables and 3) Outer join conditions have common partitions that are partitions in the view as well
 * <p>
 * A column is directly mapped to a base table column if it is derived directly or transitively from the base table column,
 * by only selecting a column or an aliased column without any function or operator applied.
 * For example, with SELECT column_b AS column_a, column_a is directly mapped to column_b.
 * With SELECT column_b + column_c AS column_a, column_a is not directly mapped to any column.
 * <p>
 * {@code viewToBaseColumnMap} only contains direct column mappings.
 */
public static void validateMaterializedViewPartitionColumns(SemiTransactionalHiveMetastore metastore, MetastoreContext metastoreContext, Table viewTable, ConnectorMaterializedViewDefinition viewDefinition) {
    SchemaTableName viewName = new SchemaTableName(viewTable.getDatabaseName(), viewTable.getTableName());
    Map<String, Map<SchemaTableName, String>> viewToBaseDirectColumnMap = viewDefinition.getDirectColumnMappingsAsMap();
    if (viewToBaseDirectColumnMap.isEmpty()) {
        throw new PrestoException(NOT_SUPPORTED, format("Materialized view %s must have at least one column directly defined by a base table column.", viewName));
    }
    List<Column> viewPartitions = viewTable.getPartitionColumns();
    if (viewPartitions.isEmpty()) {
        throw new PrestoException(NOT_SUPPORTED, "Unpartitioned materialized view is not supported.");
    }
    List<Table> baseTables = viewDefinition.getBaseTables().stream().map(baseTableName -> metastore.getTable(metastoreContext, baseTableName.getSchemaName(), baseTableName.getTableName()).orElseThrow(() -> new TableNotFoundException(baseTableName))).collect(toImmutableList());
    Map<Table, List<Column>> baseTablePartitions = baseTables.stream().collect(toImmutableMap(table -> table, Table::getPartitionColumns));
    for (Table baseTable : baseTablePartitions.keySet()) {
        SchemaTableName schemaBaseTable = new SchemaTableName(baseTable.getDatabaseName(), baseTable.getTableName());
        if (!isCommonPartitionFound(schemaBaseTable, baseTablePartitions.get(baseTable), viewPartitions, viewToBaseDirectColumnMap)) {
            throw new PrestoException(NOT_SUPPORTED, format("Materialized view %s must have at least one partition column that exists in %s as well", viewName, baseTable.getTableName()));
        }
        if (viewDefinition.getBaseTablesOnOuterJoinSide().contains(schemaBaseTable) && viewToBaseTableOnOuterJoinSideIndirectMappedPartitions(viewDefinition, baseTable).get().isEmpty()) {
            throw new PrestoException(NOT_SUPPORTED, format("Outer join conditions in Materialized view %s must have at least one common partition equality constraint", viewName));
        }
    }
}
Also used : DateTimeZone(org.joda.time.DateTimeZone) Table(com.facebook.presto.hive.metastore.Table) Column(com.facebook.presto.hive.metastore.Column) HiveUtil.getPartitionKeyColumnHandles(com.facebook.presto.hive.HiveUtil.getPartitionKeyColumnHandles) MetastoreContext(com.facebook.presto.hive.metastore.MetastoreContext) HIVE_INVALID_PARTITION_VALUE(com.facebook.presto.hive.HiveErrorCode.HIVE_INVALID_PARTITION_VALUE) HashMap(java.util.HashMap) PrestoException(com.facebook.presto.spi.PrestoException) MetastoreUtil.toPartitionNamesAndValues(com.facebook.presto.hive.metastore.MetastoreUtil.toPartitionNamesAndValues) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) SchemaTableName(com.facebook.presto.spi.SchemaTableName) ImmutableList(com.google.common.collect.ImmutableList) TupleDomain.extractFixedValues(com.facebook.presto.common.predicate.TupleDomain.extractFixedValues) TypeManager(com.facebook.presto.common.type.TypeManager) Map(java.util.Map) ConnectorMaterializedViewDefinition(com.facebook.presto.spi.ConnectorMaterializedViewDefinition) MaterializedDataPredicates(com.facebook.presto.spi.MaterializedViewStatus.MaterializedDataPredicates) Type(com.facebook.presto.common.type.Type) Collections.emptyMap(java.util.Collections.emptyMap) NullableValue(com.facebook.presto.common.predicate.NullableValue) ImmutableMap(com.google.common.collect.ImmutableMap) HIVE_INVALID_METADATA(com.facebook.presto.hive.HiveErrorCode.HIVE_INVALID_METADATA) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) Set(java.util.Set) SemiTransactionalHiveMetastore(com.facebook.presto.hive.metastore.SemiTransactionalHiveMetastore) Collectors(java.util.stream.Collectors) TupleDomain(com.facebook.presto.common.predicate.TupleDomain) String.format(java.lang.String.format) List(java.util.List) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) TableNotFoundException(com.facebook.presto.spi.TableNotFoundException) NOT_SUPPORTED(com.facebook.presto.spi.StandardErrorCode.NOT_SUPPORTED) Optional(java.util.Optional) HiveUtil.parsePartitionValue(com.facebook.presto.hive.HiveUtil.parsePartitionValue) TupleDomain.toLinkedMap(com.facebook.presto.common.predicate.TupleDomain.toLinkedMap) Table(com.facebook.presto.hive.metastore.Table) PrestoException(com.facebook.presto.spi.PrestoException) SchemaTableName(com.facebook.presto.spi.SchemaTableName) TableNotFoundException(com.facebook.presto.spi.TableNotFoundException) Column(com.facebook.presto.hive.metastore.Column) ImmutableList(com.google.common.collect.ImmutableList) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) List(java.util.List) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) Collections.emptyMap(java.util.Collections.emptyMap) ImmutableMap(com.google.common.collect.ImmutableMap) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) TupleDomain.toLinkedMap(com.facebook.presto.common.predicate.TupleDomain.toLinkedMap)

Example 7 with ConnectorMaterializedViewDefinition

use of com.facebook.presto.spi.ConnectorMaterializedViewDefinition in project presto by prestodb.

the class HiveMaterializedViewUtils method viewToBaseTableOnOuterJoinSideIndirectMappedPartitions.

// Every table on outer join side, must have a partition which is in EQ clause and present in Materialized View as well.
// For a given base table, this function computes partition columns of Materialized View which are not directly mapped to base table,
// and are directly mapped to some other base table which is not on outer join side.
// For example:
// Materialized View: SELECT t1_a as t1.a, t2_a as t2.a FROM t1 LEFT JOIN t2 ON t1.a = t2.a, partitioned by [t1_a, t2_a]
// baseTable: t2, partitioned by [a]
// Output: t1_a -> t2.a
public static Optional<Map<String, String>> viewToBaseTableOnOuterJoinSideIndirectMappedPartitions(ConnectorMaterializedViewDefinition viewDefinition, Table baseTable) {
    SchemaTableName schemaBaseTable = new SchemaTableName(baseTable.getDatabaseName(), baseTable.getTableName());
    if (!viewDefinition.getBaseTablesOnOuterJoinSide().contains(schemaBaseTable)) {
        return Optional.empty();
    }
    Map<String, String> viewToBaseIndirectMappedColumns = new HashMap<>();
    Map<String, Map<SchemaTableName, String>> columnMappings = viewDefinition.getColumnMappingsAsMap();
    Map<String, Map<SchemaTableName, String>> directColumnMappings = viewDefinition.getDirectColumnMappingsAsMap();
    for (String viewPartition : viewDefinition.getValidRefreshColumns().orElse(ImmutableList.of())) {
        String baseTablePartition = columnMappings.get(viewPartition).get(schemaBaseTable);
        // Check if it is a base table partition column
        if (baseTable.getPartitionColumns().stream().noneMatch(col -> col.getName().equals(baseTablePartition))) {
            continue;
        }
        // For e.g. in case of left outer join, we want to find partition which maps to left table
        if (directColumnMappings.get(viewPartition).keySet().stream().allMatch(e -> !e.equals(schemaBaseTable)) && directColumnMappings.get(viewPartition).keySet().stream().allMatch(t -> !viewDefinition.getBaseTablesOnOuterJoinSide().contains(t))) {
            viewToBaseIndirectMappedColumns.put(viewPartition, baseTablePartition);
        }
    }
    return Optional.of(viewToBaseIndirectMappedColumns);
}
Also used : DateTimeZone(org.joda.time.DateTimeZone) Table(com.facebook.presto.hive.metastore.Table) Column(com.facebook.presto.hive.metastore.Column) HiveUtil.getPartitionKeyColumnHandles(com.facebook.presto.hive.HiveUtil.getPartitionKeyColumnHandles) MetastoreContext(com.facebook.presto.hive.metastore.MetastoreContext) HIVE_INVALID_PARTITION_VALUE(com.facebook.presto.hive.HiveErrorCode.HIVE_INVALID_PARTITION_VALUE) HashMap(java.util.HashMap) PrestoException(com.facebook.presto.spi.PrestoException) MetastoreUtil.toPartitionNamesAndValues(com.facebook.presto.hive.metastore.MetastoreUtil.toPartitionNamesAndValues) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) SchemaTableName(com.facebook.presto.spi.SchemaTableName) ImmutableList(com.google.common.collect.ImmutableList) TupleDomain.extractFixedValues(com.facebook.presto.common.predicate.TupleDomain.extractFixedValues) TypeManager(com.facebook.presto.common.type.TypeManager) Map(java.util.Map) ConnectorMaterializedViewDefinition(com.facebook.presto.spi.ConnectorMaterializedViewDefinition) MaterializedDataPredicates(com.facebook.presto.spi.MaterializedViewStatus.MaterializedDataPredicates) Type(com.facebook.presto.common.type.Type) Collections.emptyMap(java.util.Collections.emptyMap) NullableValue(com.facebook.presto.common.predicate.NullableValue) ImmutableMap(com.google.common.collect.ImmutableMap) HIVE_INVALID_METADATA(com.facebook.presto.hive.HiveErrorCode.HIVE_INVALID_METADATA) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) Set(java.util.Set) SemiTransactionalHiveMetastore(com.facebook.presto.hive.metastore.SemiTransactionalHiveMetastore) Collectors(java.util.stream.Collectors) TupleDomain(com.facebook.presto.common.predicate.TupleDomain) String.format(java.lang.String.format) List(java.util.List) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) TableNotFoundException(com.facebook.presto.spi.TableNotFoundException) NOT_SUPPORTED(com.facebook.presto.spi.StandardErrorCode.NOT_SUPPORTED) Optional(java.util.Optional) HiveUtil.parsePartitionValue(com.facebook.presto.hive.HiveUtil.parsePartitionValue) TupleDomain.toLinkedMap(com.facebook.presto.common.predicate.TupleDomain.toLinkedMap) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) SchemaTableName(com.facebook.presto.spi.SchemaTableName) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) Collections.emptyMap(java.util.Collections.emptyMap) ImmutableMap(com.google.common.collect.ImmutableMap) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) TupleDomain.toLinkedMap(com.facebook.presto.common.predicate.TupleDomain.toLinkedMap)

Example 8 with ConnectorMaterializedViewDefinition

use of com.facebook.presto.spi.ConnectorMaterializedViewDefinition in project presto by prestodb.

the class HiveMetadata method createMaterializedView.

@Override
public void createMaterializedView(ConnectorSession session, ConnectorTableMetadata viewMetadata, ConnectorMaterializedViewDefinition viewDefinition, boolean ignoreExisting) {
    if (isExternalTable(viewMetadata.getProperties())) {
        throw new PrestoException(INVALID_TABLE_PROPERTY, "Specifying external location for materialized view is not supported.");
    }
    Table basicTable = prepareTable(session, viewMetadata, MATERIALIZED_VIEW);
    viewDefinition = new ConnectorMaterializedViewDefinition(viewDefinition.getOriginalSql(), viewDefinition.getSchema(), viewDefinition.getTable(), viewDefinition.getBaseTables(), viewDefinition.getOwner(), viewDefinition.getColumnMappings(), viewDefinition.getBaseTablesOnOuterJoinSide(), Optional.of(getPartitionedBy(viewMetadata.getProperties())));
    Map<String, String> parameters = ImmutableMap.<String, String>builder().putAll(basicTable.getParameters()).put(PRESTO_MATERIALIZED_VIEW_FLAG, "true").build();
    Table viewTable = Table.builder(basicTable).setParameters(parameters).setViewOriginalText(Optional.of(encodeMaterializedViewData(MATERIALIZED_VIEW_JSON_CODEC.toJson(viewDefinition)))).setViewExpandedText(Optional.of("/* Presto Materialized View */")).build();
    MetastoreContext metastoreContext = getMetastoreContext(session);
    validateMaterializedViewPartitionColumns(metastore, metastoreContext, viewTable, viewDefinition);
    try {
        PrincipalPrivileges principalPrivileges = buildInitialPrivilegeSet(viewTable.getOwner());
        metastore.createTable(session, viewTable, principalPrivileges, Optional.empty(), ignoreExisting, new PartitionStatistics(createEmptyStatistics(), ImmutableMap.of()));
    } catch (TableAlreadyExistsException e) {
        throw new MaterializedViewAlreadyExistsException(e.getTableName());
    }
}
Also used : SystemTable(com.facebook.presto.spi.SystemTable) DwrfTableEncryptionProperties.forTable(com.facebook.presto.hive.DwrfTableEncryptionProperties.forTable) HiveUtil.translateHiveUnsupportedTypeForTemporaryTable(com.facebook.presto.hive.HiveUtil.translateHiveUnsupportedTypeForTemporaryTable) Table(com.facebook.presto.hive.metastore.Table) HiveUtil.translateHiveUnsupportedTypesForTemporaryTable(com.facebook.presto.hive.HiveUtil.translateHiveUnsupportedTypesForTemporaryTable) HiveTableProperties.getEncryptTable(com.facebook.presto.hive.HiveTableProperties.getEncryptTable) HiveSessionProperties.shouldCreateEmptyBucketFilesForTemporaryTable(com.facebook.presto.hive.HiveSessionProperties.shouldCreateEmptyBucketFilesForTemporaryTable) HiveTableProperties.isExternalTable(com.facebook.presto.hive.HiveTableProperties.isExternalTable) PrincipalPrivileges(com.facebook.presto.hive.metastore.PrincipalPrivileges) Statistics.createEmptyPartitionStatistics(com.facebook.presto.hive.metastore.Statistics.createEmptyPartitionStatistics) PartitionStatistics(com.facebook.presto.hive.metastore.PartitionStatistics) MetastoreContext(com.facebook.presto.hive.metastore.MetastoreContext) ConnectorMaterializedViewDefinition(com.facebook.presto.spi.ConnectorMaterializedViewDefinition) PrestoException(com.facebook.presto.spi.PrestoException)

Example 9 with ConnectorMaterializedViewDefinition

use of com.facebook.presto.spi.ConnectorMaterializedViewDefinition in project presto by prestodb.

the class AddColumnTask method execute.

@Override
public ListenableFuture<?> execute(AddColumn statement, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, Session session, List<Expression> parameters, WarningCollector warningCollector) {
    QualifiedObjectName tableName = createQualifiedObjectName(session, statement, statement.getName());
    Optional<TableHandle> tableHandle = metadata.getTableHandle(session, tableName);
    if (!tableHandle.isPresent()) {
        if (!statement.isTableExists()) {
            throw new SemanticException(MISSING_TABLE, statement, "Table '%s' does not exist", tableName);
        }
        return immediateFuture(null);
    }
    Optional<ConnectorMaterializedViewDefinition> optionalMaterializedView = metadata.getMaterializedView(session, tableName);
    if (optionalMaterializedView.isPresent()) {
        if (!statement.isTableExists()) {
            throw new SemanticException(NOT_SUPPORTED, statement, "'%s' is a materialized view, and add column is not supported", tableName);
        }
        return immediateFuture(null);
    }
    ConnectorId connectorId = metadata.getCatalogHandle(session, tableName.getCatalogName()).orElseThrow(() -> new PrestoException(NOT_FOUND, "Catalog does not exist: " + tableName.getCatalogName()));
    accessControl.checkCanAddColumns(session.getRequiredTransactionId(), session.getIdentity(), session.getAccessControlContext(), tableName);
    Map<String, ColumnHandle> columnHandles = metadata.getColumnHandles(session, tableHandle.get());
    ColumnDefinition element = statement.getColumn();
    Type type;
    try {
        type = metadata.getType(parseTypeSignature(element.getType()));
    } catch (IllegalArgumentException e) {
        throw new SemanticException(TYPE_MISMATCH, element, "Unknown type '%s' for column '%s'", element.getType(), element.getName());
    }
    if (type.equals(UNKNOWN)) {
        throw new SemanticException(TYPE_MISMATCH, element, "Unknown type '%s' for column '%s'", element.getType(), element.getName());
    }
    if (columnHandles.containsKey(element.getName().getValue().toLowerCase(ENGLISH))) {
        if (!statement.isColumnNotExists()) {
            throw new SemanticException(COLUMN_ALREADY_EXISTS, statement, "Column '%s' already exists", element.getName());
        }
        return immediateFuture(null);
    }
    if (!element.isNullable() && !metadata.getConnectorCapabilities(session, connectorId).contains(NOT_NULL_COLUMN_CONSTRAINT)) {
        throw new SemanticException(NOT_SUPPORTED, element, "Catalog '%s' does not support NOT NULL for column '%s'", connectorId.getCatalogName(), element.getName());
    }
    Map<String, Expression> sqlProperties = mapFromProperties(element.getProperties());
    Map<String, Object> columnProperties = metadata.getColumnPropertyManager().getProperties(connectorId, tableName.getCatalogName(), sqlProperties, session, metadata, parameters);
    ColumnMetadata column = new ColumnMetadata(element.getName().getValue(), type, element.isNullable(), element.getComment().orElse(null), null, false, columnProperties);
    metadata.addColumn(session, tableHandle.get(), column);
    return immediateFuture(null);
}
Also used : ColumnHandle(com.facebook.presto.spi.ColumnHandle) ColumnMetadata(com.facebook.presto.spi.ColumnMetadata) ConnectorMaterializedViewDefinition(com.facebook.presto.spi.ConnectorMaterializedViewDefinition) PrestoException(com.facebook.presto.spi.PrestoException) QualifiedObjectName(com.facebook.presto.common.QualifiedObjectName) MetadataUtil.createQualifiedObjectName(com.facebook.presto.metadata.MetadataUtil.createQualifiedObjectName) ColumnDefinition(com.facebook.presto.sql.tree.ColumnDefinition) Type(com.facebook.presto.common.type.Type) Expression(com.facebook.presto.sql.tree.Expression) TableHandle(com.facebook.presto.spi.TableHandle) SemanticException(com.facebook.presto.sql.analyzer.SemanticException) ConnectorId(com.facebook.presto.spi.ConnectorId)

Example 10 with ConnectorMaterializedViewDefinition

use of com.facebook.presto.spi.ConnectorMaterializedViewDefinition in project presto by prestodb.

the class DropColumnTask method execute.

@Override
public ListenableFuture<?> execute(DropColumn statement, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, Session session, List<Expression> parameters, WarningCollector warningCollector) {
    QualifiedObjectName tableName = createQualifiedObjectName(session, statement, statement.getTable());
    Optional<TableHandle> tableHandleOptional = metadata.getTableHandle(session, tableName);
    if (!tableHandleOptional.isPresent()) {
        if (!statement.isTableExists()) {
            throw new SemanticException(MISSING_TABLE, statement, "Table '%s' does not exist", tableName);
        }
        return immediateFuture(null);
    }
    Optional<ConnectorMaterializedViewDefinition> optionalMaterializedView = metadata.getMaterializedView(session, tableName);
    if (optionalMaterializedView.isPresent()) {
        if (!statement.isTableExists()) {
            throw new SemanticException(NOT_SUPPORTED, statement, "'%s' is a materialized view, and drop column is not supported", tableName);
        }
        return immediateFuture(null);
    }
    TableHandle tableHandle = tableHandleOptional.get();
    String column = statement.getColumn().getValue().toLowerCase(ENGLISH);
    accessControl.checkCanDropColumn(session.getRequiredTransactionId(), session.getIdentity(), session.getAccessControlContext(), tableName);
    ColumnHandle columnHandle = metadata.getColumnHandles(session, tableHandle).get(column);
    if (columnHandle == null) {
        if (!statement.isColumnExists()) {
            throw new SemanticException(MISSING_COLUMN, statement, "Column '%s' does not exist", column);
        }
        return immediateFuture(null);
    }
    if (metadata.getColumnMetadata(session, tableHandle, columnHandle).isHidden()) {
        throw new SemanticException(NOT_SUPPORTED, statement, "Cannot drop hidden column");
    }
    if (metadata.getTableMetadata(session, tableHandle).getColumns().stream().filter(info -> !info.isHidden()).count() <= 1) {
        throw new SemanticException(NOT_SUPPORTED, statement, "Cannot drop the only column in a table");
    }
    metadata.dropColumn(session, tableHandle, columnHandle);
    return immediateFuture(null);
}
Also used : ColumnHandle(com.facebook.presto.spi.ColumnHandle) ConnectorMaterializedViewDefinition(com.facebook.presto.spi.ConnectorMaterializedViewDefinition) TableHandle(com.facebook.presto.spi.TableHandle) MetadataUtil.createQualifiedObjectName(com.facebook.presto.metadata.MetadataUtil.createQualifiedObjectName) QualifiedObjectName(com.facebook.presto.common.QualifiedObjectName) SemanticException(com.facebook.presto.sql.analyzer.SemanticException)

Aggregations

ConnectorMaterializedViewDefinition (com.facebook.presto.spi.ConnectorMaterializedViewDefinition)13 QualifiedObjectName (com.facebook.presto.common.QualifiedObjectName)7 MetadataUtil.createQualifiedObjectName (com.facebook.presto.metadata.MetadataUtil.createQualifiedObjectName)7 SemanticException (com.facebook.presto.sql.analyzer.SemanticException)7 PrestoException (com.facebook.presto.spi.PrestoException)6 TableHandle (com.facebook.presto.spi.TableHandle)6 Type (com.facebook.presto.common.type.Type)4 MetastoreContext (com.facebook.presto.hive.metastore.MetastoreContext)4 Table (com.facebook.presto.hive.metastore.Table)4 NullableValue (com.facebook.presto.common.predicate.NullableValue)3 TupleDomain (com.facebook.presto.common.predicate.TupleDomain)3 ColumnHandle (com.facebook.presto.spi.ColumnHandle)3 SchemaTableName (com.facebook.presto.spi.SchemaTableName)3 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)3 List (java.util.List)3 Map (java.util.Map)3 Optional (java.util.Optional)3 TupleDomain.extractFixedValues (com.facebook.presto.common.predicate.TupleDomain.extractFixedValues)2 TupleDomain.toLinkedMap (com.facebook.presto.common.predicate.TupleDomain.toLinkedMap)2 TypeManager (com.facebook.presto.common.type.TypeManager)2