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

com.facebook.presto.jdbc.internal.spi.ConnectorMaterializedViewDefinition Maven / Gradle / Ivy

There is a newer version: 0.289
Show newest version
/*
 * 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.facebook.presto.jdbc.internal.spi;

import com.facebook.presto.jdbc.internal.jackson.annotation.JsonCreator;
import com.facebook.presto.jdbc.internal.jackson.annotation.JsonIgnore;
import com.facebook.presto.jdbc.internal.jackson.annotation.JsonProperty;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

import static java.util.Collections.unmodifiableList;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toMap;

public final class ConnectorMaterializedViewDefinition
{
    private final String originalSql;
    private final String schema;
    private final String table;
    private final List baseTables;
    private final Optional owner;
    private final List columnMappings;
    private final List baseTablesOnOuterJoinSide;
    private final Optional> validRefreshColumns;

    @JsonCreator
    public ConnectorMaterializedViewDefinition(
            @JsonProperty("originalSql") String originalSql,
            @JsonProperty("schema") String schema,
            @JsonProperty("table") String table,
            @JsonProperty("baseTables") List baseTables,
            @JsonProperty("owner") Optional owner,
            @JsonProperty("columnMapping") List columnMappings,
            @JsonProperty("baseTablesOnOuterJoinSide") List baseTablesOnOuterJoinSide,
            @JsonProperty("validRefreshColumns") Optional> validRefreshColumns)
    {
        this.originalSql = requireNonNull(originalSql, "originalSql is null");
        this.schema = requireNonNull(schema, "schema is null");
        this.table = requireNonNull(table, "table is null");
        this.baseTables = unmodifiableList(new ArrayList<>(requireNonNull(baseTables, "baseTables is null")));
        this.owner = requireNonNull(owner, "owner is null");
        this.columnMappings = unmodifiableList(new ArrayList<>(requireNonNull(columnMappings, "columnMappings is null")));
        this.baseTablesOnOuterJoinSide = unmodifiableList(new ArrayList<>(requireNonNull(baseTablesOnOuterJoinSide, "baseTablesOnOuterJoinSide is null")));
        this.validRefreshColumns = requireNonNull(validRefreshColumns, "validRefreshColumns is null").map(columns -> unmodifiableList(new ArrayList<>(columns)));
    }

    @JsonIgnore
    public ConnectorMaterializedViewDefinition(
            String originalSql,
            String schema,
            String table,
            List baseTables,
            Optional owner,
            Map> originalColumnMapping,
            Map> nonNullColumnMappings,
            List baseTablesOnOuterJoinSide,
            Optional> validRefreshColumns)
    {
        this(
                originalSql,
                schema,
                table,
                baseTables,
                owner,
                convertFromMapToColumnMappings(
                        requireNonNull(originalColumnMapping, "originalColumnMapping is null"),
                        requireNonNull(nonNullColumnMappings, "nonNullColumnMappings is null"),
                        new SchemaTableName(schema, table)),
                baseTablesOnOuterJoinSide,
                validRefreshColumns);
    }

    @JsonProperty
    public String getOriginalSql()
    {
        return originalSql;
    }

    @JsonProperty
    public String getSchema()
    {
        return schema;
    }

    @JsonProperty
    public String getTable()
    {
        return table;
    }

    @JsonProperty
    public List getBaseTables()
    {
        return baseTables;
    }

    @JsonProperty
    public Optional getOwner()
    {
        return owner;
    }

    @JsonProperty
    public List getColumnMappings()
    {
        return columnMappings;
    }

    @JsonProperty
    public List getBaseTablesOnOuterJoinSide()
    {
        return baseTablesOnOuterJoinSide;
    }

    @JsonProperty
    public Optional> getValidRefreshColumns()
    {
        return validRefreshColumns;
    }

    @Override
    public String toString()
    {
        StringBuilder sb = new StringBuilder("ConnectorMaterializedViewDefinition{");
        sb.append("originalSql=").append(originalSql);
        sb.append(",schema=").append(schema);
        sb.append(",table=").append(table);
        sb.append(",baseTables=").append(baseTables);
        sb.append(",owner=").append(owner.orElse(null));
        sb.append(",columnMappings=").append(columnMappings);
        sb.append(",baseTablesOnOuterJoinSide=").append(baseTablesOnOuterJoinSide);
        sb.append(",validRefreshColumns=").append(validRefreshColumns.orElse(null));
        sb.append("}");
        return sb.toString();
    }

    @JsonIgnore
    public Map> getColumnMappingsAsMap()
    {
        return columnMappings.stream()
                .collect(toMap(
                        mapping -> mapping.getViewColumn().getColumnName(),
                        mapping -> mapping.getBaseTableColumns().stream().collect(toMap(TableColumn::getTableName, TableColumn::getColumnName))));
    }

    @JsonIgnore
    public Map> getDirectColumnMappingsAsMap()
    {
        return columnMappings.stream()
                .collect(toMap(
                        mapping -> mapping.getViewColumn().getColumnName(),
                        mapping -> mapping.getBaseTableColumns().stream().filter(col -> col.isDirectMapped().orElse(true)).collect(toMap(TableColumn::getTableName, TableColumn::getColumnName))));
    }

    @JsonIgnore
    private static List convertFromMapToColumnMappings(Map> originalColumnMappings, Map> directColumnMappings, SchemaTableName sourceTable)
    {
        List columnMappingList = new ArrayList<>();

        for (String sourceColumn : originalColumnMappings.keySet()) {
            TableColumn viewColumn = new TableColumn(sourceTable, sourceColumn, true);
            Map directMappings = directColumnMappings.get(sourceColumn);

            List baseTableColumns = new ArrayList<>();
            for (SchemaTableName baseTable : originalColumnMappings.get(sourceColumn).keySet()) {
                String column = originalColumnMappings.get(sourceColumn).get(baseTable);
                boolean isDirectMapped = directMappings != null && (directMappings.containsKey(baseTable) && directMappings.get(baseTable) == column);
                baseTableColumns.add(new TableColumn(baseTable, column, isDirectMapped));
            }

            columnMappingList.add(new ColumnMapping(viewColumn, unmodifiableList(baseTableColumns)));
        }

        return unmodifiableList(columnMappingList);
    }

    public static final class ColumnMapping
    {
        private final TableColumn viewColumn;
        private final List baseTableColumns;

        @JsonCreator
        public ColumnMapping(
                @JsonProperty("viewColumn") TableColumn viewColumn,
                @JsonProperty("baseTableColumns") List baseTableColumns)
        {
            this.viewColumn = requireNonNull(viewColumn, "viewColumn is null");
            this.baseTableColumns = unmodifiableList(new ArrayList<>(requireNonNull(baseTableColumns, "baseTableColumns is null")));
        }

        @JsonProperty
        public TableColumn getViewColumn()
        {
            return viewColumn;
        }

        @JsonProperty
        public List getBaseTableColumns()
        {
            return baseTableColumns;
        }

        @Override
        public String toString()
        {
            StringBuilder sb = new StringBuilder("ColumnMapping{");
            sb.append("viewColumn=").append(viewColumn);
            sb.append(",baseTableColumns=").append(baseTableColumns);
            sb.append("}");
            return sb.toString();
        }
    }

    public static final class TableColumn
    {
        private final SchemaTableName tableName;
        private final String columnName;
        // This signifies whether the mapping is direct or not.
        // Mapping is always direct in inner join case. In the outer join case, only the mapping from a column to its source column in the join input table is direct.
        // For e.g. in case of SELECT t1_a as t1.a, t2_a as t2.a FROM t1 LEFT JOIN t2 ON t1.a = t2.a
        // t1_a -> t1.a is direct mapped
        // t1_a -> t2.a is NOT direct mapped(as t1,t2 are in outer join)
        // t2_a -> t2.a is direct mapped(value can become null but column mapping is not altered)
        // t2_a -> t1.a is NOT direct mapped(as t1,t2 are in outer join)
        private final Optional isDirectMapped;

        @JsonCreator
        public TableColumn(
                @JsonProperty("tableName") SchemaTableName tableName,
                @JsonProperty("columnName") String columnName,
                @JsonProperty("isDirectMapped") Optional isDirectMapped)
        {
            this.tableName = requireNonNull(tableName, "tableName is null");
            this.columnName = requireNonNull(columnName, "columnName is null");
            this.isDirectMapped = requireNonNull(isDirectMapped, "isDirectMapped is null");
        }

        public TableColumn(
                SchemaTableName tableName,
                String columnName,
                boolean isDirectMapped)
        {
            this(tableName, columnName, Optional.of(isDirectMapped));
        }

        @JsonProperty
        public SchemaTableName getTableName()
        {
            return tableName;
        }

        @JsonProperty
        public String getColumnName()
        {
            return columnName;
        }

        @JsonProperty
        public Optional isDirectMapped()
        {
            return isDirectMapped;
        }

        @Override
        public int hashCode()
        {
            return Objects.hash(tableName, columnName);
        }

        @Override
        public boolean equals(Object o)
        {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }

            TableColumn that = (TableColumn) o;
            return Objects.equals(this.columnName, that.columnName) &&
                    Objects.equals(this.tableName, that.tableName) &&
                    Objects.equals(this.isDirectMapped, that.isDirectMapped);
        }

        @Override
        public String toString()
        {
            return tableName + ":" + columnName + (isDirectMapped.orElse(true) ? "" : "isDirectMapped:false");
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy