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

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

There is a newer version: 5.4.0
Show newest version
/*
 * 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.util.mapping.IntPair;

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

import com.hazelcast.org.checkerframework.checker.nullness.qual.Nullable;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/** Mutable version of {@link LatticeNode}, used while a graph is being
 * built. */
class MutableNode {
  final LatticeTable table;
  final @Nullable MutableNode parent;
  final @Nullable Step step;
  int startCol;
  int endCol;
  @Nullable String alias;
  final List children = new ArrayList<>();

  /** Comparator for sorting children within a parent. */
  static final Ordering ORDERING =
      Ordering.from(
          new Comparator() {
            @Override public int compare(MutableNode o1, MutableNode o2) {
              int c = Ordering.natural().lexicographical().compare(
                  o1.table.t.getQualifiedName(), o2.table.t.getQualifiedName());
              if (c == 0 && o1.step != null && o2.step != null) {
                // The nodes have the same table. Now compare them based on the
                // columns they use as foreign key.
                c = Ordering.natural().lexicographical().compare(
                    IntPair.left(o1.step.keys), IntPair.left(o2.step.keys));
              }
              return c;
            }
          });

  /** Creates a root node. */
  MutableNode(LatticeTable table) {
    this(table, null, null);
  }

  /** Creates a non-root node. */
  @SuppressWarnings("argument.type.incompatible")
  MutableNode(LatticeTable table, @Nullable MutableNode parent, @Nullable Step step) {
    this.table = Objects.requireNonNull(table, "table");
    this.parent = parent;
    this.step = step;
    if (parent != null) {
      parent.children.add(this);
      Collections.sort(parent.children, ORDERING);
    }
  }

  /** Populates a flattened list of mutable nodes. */
  void flatten(List flatNodes) {
    flatNodes.add(this);
    for (MutableNode child : children) {
      child.flatten(flatNodes);
    }
  }

  /** Returns whether this node is cylic, in an undirected sense; that is,
   * whether the same descendant can be reached by more than one route. */
  boolean isCyclic() {
    final Set descendants = new HashSet<>();
    return isCyclicRecurse(descendants);
  }

  private boolean isCyclicRecurse(Set descendants) {
    if (!descendants.add(this)) {
      return true;
    }
    for (MutableNode child : children) {
      if (child.isCyclicRecurse(descendants)) {
        return true;
      }
    }
    return false;
  }

  void addPath(Path path, @Nullable String alias) {
    MutableNode n = this;
    for (Step step1 : path.steps) {
      MutableNode n2 = n.findChild(step1);
      if (n2 == null) {
        n2 = new MutableNode(step1.target(), n, step1);
        if (alias != null) {
          n2.alias = alias;
        }
      }
      n = n2;
    }
  }

  private @Nullable MutableNode findChild(Step step) {
    for (MutableNode child : children) {
      if (Objects.equals(child.table, step.target())
          && Objects.equals(child.step, step)) {
        return child;
      }
    }
    return null;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy