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

com.hazelcast.org.apache.calcite.materialize.Step Maven / Gradle / Ivy

/*
 * 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 com.hazelcast.org.apache.calcite.materialize;

import com.hazelcast.org.apache.calcite.plan.RelOptTable;
import com.hazelcast.org.apache.calcite.util.graph.AttributedDirectedGraph;
import com.hazelcast.org.apache.calcite.util.graph.DefaultEdge;
import com.hazelcast.org.apache.calcite.util.mapping.IntPair;

import com.hazelcast.com.google.common.collect.ImmutableList;
import com.hazelcast.com.google.common.collect.Ordering;

import java.util.List;
import java.util.Objects;

/** Edge in the join graph.
 *
 * 

It is directed: the "parent" must be the "many" side containing the * foreign key, and the "target" is the "one" side containing the primary * key. For example, EMP → DEPT. * *

When created via * {@link LatticeSpace#addEdge(LatticeTable, LatticeTable, List)} * it is unique within the {@link LatticeSpace}. */ class Step extends DefaultEdge { final List keys; /** String representation of {@link #keys}. Computing the string requires a * {@link LatticeSpace}, so we pre-compute it before construction. */ final String keyString; private Step(LatticeTable source, LatticeTable target, List keys, String keyString) { super(source, target); this.keys = ImmutableList.copyOf(keys); this.keyString = Objects.requireNonNull(keyString); assert IntPair.ORDERING.isStrictlyOrdered(keys); // ordered and unique } /** Creates a Step. */ static Step create(LatticeTable source, LatticeTable target, List keys, LatticeSpace space) { final StringBuilder b = new StringBuilder(); for (IntPair key : keys) { b.append(' ') .append(space.fieldName(source, key.source)) .append(':') .append(space.fieldName(target, key.target)); } return new Step(source, target, keys, b.toString()); } @Override public int hashCode() { return Objects.hash(source, target, keys); } @Override public boolean equals(Object obj) { return this == obj || obj instanceof Step && ((Step) obj).source.equals(source) && ((Step) obj).target.equals(target) && ((Step) obj).keys.equals(keys); } @Override public String toString() { return "Step(" + source + ", " + target + "," + keyString + ")"; } LatticeTable source() { return (LatticeTable) source; } LatticeTable target() { return (LatticeTable) target; } boolean isBackwards(SqlStatisticProvider statisticProvider) { final RelOptTable sourceTable = source().t; final List sourceColumns = IntPair.left(keys); final RelOptTable targetTable = target().t; final List targetColumns = IntPair.right(keys); final boolean noDerivedSourceColumns = sourceColumns.stream().allMatch(i -> i < sourceTable.getRowType().getFieldCount()); final boolean noDerivedTargetColumns = targetColumns.stream().allMatch(i -> i < targetTable.getRowType().getFieldCount()); final boolean forwardForeignKey = noDerivedSourceColumns && noDerivedTargetColumns && statisticProvider.isForeignKey(sourceTable, sourceColumns, targetTable, targetColumns) && statisticProvider.isKey(targetTable, targetColumns); final boolean backwardForeignKey = noDerivedSourceColumns && noDerivedTargetColumns && statisticProvider.isForeignKey(targetTable, targetColumns, sourceTable, sourceColumns) && statisticProvider.isKey(sourceTable, sourceColumns); if (backwardForeignKey != forwardForeignKey) { return backwardForeignKey; } // Tie-break if it's a foreign key in neither or both directions return compare(sourceTable, sourceColumns, targetTable, targetColumns) < 0; } /** Arbitrarily compares (table, columns). */ private static int compare(RelOptTable table1, List columns1, RelOptTable table2, List columns2) { int c = Ordering.natural().lexicographical() .compare(table1.getQualifiedName(), table2.getQualifiedName()); if (c == 0) { c = Ordering.natural().lexicographical() .compare(columns1, columns2); } return c; } /** Temporary method. We should use (inferred) primary keys to figure out * the direction of steps. */ private double cardinality(SqlStatisticProvider statisticProvider, LatticeTable table) { return statisticProvider.tableCardinality(table.t); } /** Creates {@link Step} instances. */ static class Factory implements AttributedDirectedGraph.AttributedEdgeFactory< LatticeTable, Step> { private final LatticeSpace space; Factory(LatticeSpace space) { this.space = Objects.requireNonNull(space); } public Step createEdge(LatticeTable source, LatticeTable target) { throw new UnsupportedOperationException(); } public Step createEdge(LatticeTable source, LatticeTable target, Object... attributes) { @SuppressWarnings("unchecked") final List keys = (List) attributes[0]; return Step.create(source, target, keys, space); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy