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

com.hazelcast.org.apache.calcite.plan.volcano.IterativeRuleQueue Maven / Gradle / Ivy

There is a newer version: 5.5.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.plan.volcano;

import com.hazelcast.org.apache.calcite.rel.RelNode;
import com.hazelcast.org.apache.calcite.rel.rules.SubstitutionRule;
import com.hazelcast.org.apache.calcite.util.trace.CalciteTrace;

import com.hazelcast.com.google.common.collect.HashMultimap;
import com.hazelcast.com.google.common.collect.Multimap;

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

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayDeque;
import java.util.HashSet;
import java.util.Queue;
import java.util.Set;

import static java.util.Objects.requireNonNull;

/**
 * Priority queue of relexps whose rules have not been called, and rule-matches
 * which have not yet been acted upon.
 */
class IterativeRuleQueue extends RuleQueue {
  //~ Static fields/initializers ---------------------------------------------

  private static final Logger LOGGER = CalciteTrace.getPlannerTracer();

  //~ Instance fields --------------------------------------------------------

  /**
   * The list of rule-matches. Initially, there is an empty {@link MatchList}.
   * As the planner invokes {@link #addMatch(VolcanoRuleMatch)} the rule-match
   * is added to the appropriate MatchList(s). As the planner completes the
   * match, the matching entry is removed from this list to avoid unused work.
   */
  final MatchList matchList = new MatchList();

  //~ Constructors -----------------------------------------------------------

  IterativeRuleQueue(VolcanoPlanner planner) {
    super(planner);
  }

  //~ Methods ----------------------------------------------------------------
  /**
   * Clear internal data structure for this rule queue.
   */
  @Override public boolean clear() {
    boolean empty = true;
    if (!matchList.queue.isEmpty() || !matchList.preQueue.isEmpty()) {
      empty = false;
    }
    matchList.clear();
    return !empty;
  }

  /**
   * Add a rule match.
   */
  @Override public void addMatch(VolcanoRuleMatch match) {
    final String matchName = match.toString();

    if (!matchList.names.add(matchName)) {
      // Identical match has already been added.
      return;
    }

    LOGGER.trace("Rule-match queued: {}", matchName);

    matchList.offer(match);

    matchList.matchMap.put(
        requireNonNull(planner.getSubset(match.rels[0])), match);
  }

  /**
   * Removes the rule match from the head of match list, and returns it.
   *
   * 

Returns {@code null} if there are no more matches.

* *

Note that the VolcanoPlanner may still decide to reject rule matches * which have become invalid, say if one of their operands belongs to an * obsolete set or has been pruned. * */ public @Nullable VolcanoRuleMatch popMatch() { dumpPlannerState(); VolcanoRuleMatch match; for (;;) { if (matchList.size() == 0) { return null; } dumpRuleQueue(matchList); match = matchList.poll(); if (match == null) { return null; } if (skipMatch(match)) { LOGGER.debug("Skip match: {}", match); } else { break; } } // If sets have merged since the rule match was enqueued, the match // may not be removed from the matchMap because the subset may have // changed, it is OK to leave it since the matchMap will be cleared // at the end. matchList.matchMap.remove( planner.getSubset(match.rels[0]), match); LOGGER.debug("Pop match: {}", match); return match; } /** * Dumps rules queue to the logger when debug level is set to {@code TRACE}. */ private static void dumpRuleQueue(MatchList matchList) { if (LOGGER.isTraceEnabled()) { StringBuilder b = new StringBuilder(); b.append("Rule queue:"); for (VolcanoRuleMatch rule : matchList.preQueue) { b.append("\n"); b.append(rule); } for (VolcanoRuleMatch rule : matchList.queue) { b.append("\n"); b.append(rule); } LOGGER.trace(b.toString()); } } /** * Dumps planner's state to the logger when debug level is set to {@code TRACE}. */ private void dumpPlannerState() { if (LOGGER.isTraceEnabled()) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); planner.dump(pw); pw.flush(); LOGGER.trace(sw.toString()); RelNode root = planner.getRoot(); if (root != null) { root.getCluster().invalidateMetadataQuery(); } } } //~ Inner Classes ---------------------------------------------------------- /** * MatchList represents a set of {@link VolcanoRuleMatch rule-matches}. */ private static class MatchList { /** * Rule match queue for SubstitutionRule. */ private final Queue preQueue = new ArrayDeque<>(); /** * Current list of VolcanoRuleMatches for this phase. New rule-matches * are appended to the end of this queue. * The rules are not sorted in any way. */ private final Queue queue = new ArrayDeque<>(); /** * A set of rule-match names contained in {@link #queue}. Allows fast * detection of duplicate rule-matches. */ final Set names = new HashSet<>(); /** * Multi-map of RelSubset to VolcanoRuleMatches. */ final Multimap matchMap = HashMultimap.create(); int size() { return preQueue.size() + queue.size(); } @Nullable VolcanoRuleMatch poll() { VolcanoRuleMatch match = preQueue.poll(); if (match == null) { match = queue.poll(); } return match; } void offer(VolcanoRuleMatch match) { if (match.getRule() instanceof SubstitutionRule) { preQueue.offer(match); } else { queue.offer(match); } } void clear() { preQueue.clear(); queue.clear(); names.clear(); matchMap.clear(); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy