blob: c24b54fecef2bb6271d9e856b8ab5a24dce93c32 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.drill.metastore.metadata;
import org.apache.drill.common.expression.SchemaPath;
import org.apache.drill.exec.record.metadata.ColumnMetadata;
import org.apache.drill.exec.record.metadata.TupleMetadata;
import org.apache.drill.metastore.components.tables.TableMetadataUnit;
import org.apache.drill.metastore.statistics.ColumnStatistics;
import org.apache.drill.metastore.statistics.StatisticsHolder;
import org.apache.drill.metastore.statistics.StatisticsKind;
import org.apache.drill.metastore.util.SchemaPathUtils;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* Common provider of tuple schema, column metadata, and statistics for table, partition, file or row group.
*/
public abstract class BaseMetadata implements Metadata {
public static final long UNDEFINED_TIME = -1;
protected final TableInfo tableInfo;
protected final MetadataInfo metadataInfo;
protected final TupleMetadata schema;
protected final Map<SchemaPath, ColumnStatistics<?>> columnsStatistics;
protected final Map<String, StatisticsHolder<?>> metadataStatistics;
protected final long lastModifiedTime;
protected <T extends BaseMetadataBuilder<T>> BaseMetadata(BaseMetadataBuilder<T> builder) {
this.tableInfo = builder.tableInfo;
this.metadataInfo = builder.metadataInfo;
this.schema = builder.schema;
this.columnsStatistics = builder.columnsStatistics;
this.metadataStatistics = builder.metadataStatistics.stream()
.collect(Collectors.toMap(
statistic -> statistic.getStatisticsKind().getName(),
Function.identity(),
(a, b) -> a.getStatisticsKind().isExact() ? a : b));
this.lastModifiedTime = builder.lastModifiedTime;
}
@Override
public Map<SchemaPath, ColumnStatistics<?>> getColumnsStatistics() {
return columnsStatistics;
}
@Override
public ColumnStatistics<?> getColumnStatistics(SchemaPath columnName) {
return columnsStatistics.get(columnName);
}
@Override
public TupleMetadata getSchema() {
return schema;
}
@Override
@SuppressWarnings("unchecked")
public <V> V getStatistic(StatisticsKind<V> statisticsKind) {
StatisticsHolder<V> statisticsHolder = (StatisticsHolder<V>)
metadataStatistics.get(statisticsKind.getName());
return statisticsHolder != null ? statisticsHolder.getStatisticsValue() : null;
}
@Override
public boolean containsExactStatistics(StatisticsKind<?> statisticsKind) {
StatisticsHolder<?> statisticsHolder = metadataStatistics.get(statisticsKind.getName());
return statisticsHolder != null && statisticsHolder.getStatisticsKind().isExact();
}
@Override
public <V> V getStatisticsForColumn(SchemaPath columnName, StatisticsKind<V> statisticsKind) {
return columnsStatistics.get(columnName).get(statisticsKind);
}
@Override
public ColumnMetadata getColumn(SchemaPath name) {
return SchemaPathUtils.getColumnMetadata(name, schema);
}
@Override
public TableInfo getTableInfo() {
return tableInfo;
}
@Override
public MetadataInfo getMetadataInfo() {
return metadataInfo;
}
/**
* Allows to check the time, when any files were modified.
* It is in Unix Timestamp, unit of measurement is millisecond.
* Undefined time value will be indicated using {@link #UNDEFINED_TIME} value.
*
* @return last modified time of files
*/
public long getLastModifiedTime() {
return lastModifiedTime;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof BaseMetadata)) {
return false;
}
BaseMetadata that = (BaseMetadata) o;
return lastModifiedTime == that.lastModifiedTime
&& Objects.equals(tableInfo, that.tableInfo)
&& Objects.equals(metadataInfo, that.metadataInfo)
&& Objects.equals(columnsStatistics, that.columnsStatistics)
&& Objects.equals(metadataStatistics, that.metadataStatistics)
&& (schema == that.schema
|| (schema != null && schema.isEquivalent(that.schema)));
}
@Override
public int hashCode() {
return Objects.hash(tableInfo, metadataInfo, schema,
columnsStatistics, metadataStatistics, lastModifiedTime);
}
@Override
public TableMetadataUnit toMetadataUnit() {
TableMetadataUnit.Builder builder = TableMetadataUnit.builder();
tableInfo.toMetadataUnitBuilder(builder);
metadataInfo.toMetadataUnitBuilder(builder);
if (schema != null) {
builder.schema(schema.jsonString());
}
builder.columnsStatistics(columnsStatistics.entrySet().stream()
.collect(Collectors.toMap(
entry -> entry.getKey().toString(),
entry -> entry.getValue().jsonString(),
(o, n) -> n)));
builder.metadataStatistics(metadataStatistics.values().stream()
.map(StatisticsHolder::jsonString)
.collect(Collectors.toList()));
builder.lastModifiedTime(lastModifiedTime);
toMetadataUnitBuilder(builder);
return builder.build();
}
protected abstract void toMetadataUnitBuilder(TableMetadataUnit.Builder builder);
protected abstract BaseMetadataBuilder<?> toBuilder();
public static abstract class BaseMetadataBuilder<T extends BaseMetadataBuilder<T>> {
protected TableInfo tableInfo;
protected MetadataInfo metadataInfo;
protected TupleMetadata schema;
protected Map<SchemaPath, ColumnStatistics<?>> columnsStatistics;
protected Collection<StatisticsHolder<?>> metadataStatistics;
protected long lastModifiedTime = UNDEFINED_TIME;
public T tableInfo(TableInfo tableInfo) {
this.tableInfo = tableInfo;
return self();
}
public T metadataInfo(MetadataInfo metadataInfo) {
this.metadataInfo = metadataInfo;
return self();
}
public T schema(TupleMetadata schema) {
this.schema = schema;
return self();
}
public T columnsStatistics(Map<SchemaPath, ColumnStatistics<?>> columnsStatistics) {
this.columnsStatistics = columnsStatistics;
return self();
}
public T metadataStatistics(Collection<StatisticsHolder<?>> metadataStatistics) {
this.metadataStatistics = metadataStatistics;
return self();
}
public T lastModifiedTime(long lastModifiedTime) {
this.lastModifiedTime = lastModifiedTime;
return self();
}
public T metadataUnit(TableMetadataUnit unit) {
tableInfo(TableInfo.builder().metadataUnit(unit).build());
metadataInfo(MetadataInfo.builder().metadataUnit(unit).build());
schema(TupleMetadata.of(unit.schema()));
if (unit.columnsStatistics() != null) {
columnsStatistics(unit.columnsStatistics().entrySet().stream()
.collect(Collectors.toMap(
entry -> SchemaPath.parseFromString(entry.getKey()),
entry -> ColumnStatistics.of(entry.getValue()),
(o, n) -> n)));
}
if (unit.metadataStatistics() != null) {
metadataStatistics(unit.metadataStatistics().stream()
.map(StatisticsHolder::of)
.collect(Collectors.toList()));
}
if (unit.lastModifiedTime() != null) {
lastModifiedTime(unit.lastModifiedTime());
}
return metadataUnitInternal(unit);
}
protected void checkRequiredValues() {
Objects.requireNonNull(tableInfo, "tableInfo was not set");
Objects.requireNonNull(metadataInfo, "metadataInfo was not set");
Objects.requireNonNull(columnsStatistics, "columnsStatistics were not set");
Objects.requireNonNull(metadataStatistics, "metadataStatistics were not set");
}
public abstract BaseMetadata build();
protected abstract T self();
protected abstract T metadataUnitInternal(TableMetadataUnit unit);
}
}