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

com.hazelcast.org.apache.calcite.rex.LogicVisitor 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.rex;

import com.hazelcast.org.apache.calcite.plan.RelOptUtil.Logic;

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

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

import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;

import static java.util.Objects.requireNonNull;

/**
 * Visitor pattern for traversing a tree of {@link RexNode} objects.
 */
public class LogicVisitor extends RexUnaryBiVisitor<@Nullable Logic> {
  private final RexNode seek;
  private final Collection logicCollection;

  /** Creates a LogicVisitor. */
  private LogicVisitor(RexNode seek, Collection logicCollection) {
    super(true);
    this.seek = seek;
    this.logicCollection = logicCollection;
  }

  /** Finds a suitable logic for evaluating {@code seek} within a list of
   * expressions.
   *
   * 

Chooses a logic that is safe (that is, gives the right * answer) with the fewest possibilities (that is, we prefer one that * returns [true as true, false as false, unknown as false] over one that * distinguishes false from unknown). */ public static Logic find(Logic logic, List nodes, RexNode seek) { final Set set = EnumSet.noneOf(Logic.class); final LogicVisitor visitor = new LogicVisitor(seek, set); for (RexNode node : nodes) { node.accept(visitor, logic); } // Convert FALSE (which can only exist within LogicVisitor) to // UNKNOWN_AS_TRUE. if (set.remove(Logic.FALSE)) { set.add(Logic.UNKNOWN_AS_TRUE); } switch (set.size()) { case 0: throw new IllegalArgumentException("not found: " + seek); case 1: return Iterables.getOnlyElement(set); default: return Logic.TRUE_FALSE_UNKNOWN; } } public static void collect(RexNode node, RexNode seek, Logic logic, List logicList) { node.accept(new LogicVisitor(seek, logicList), logic); // Convert FALSE (which can only exist within LogicVisitor) to // UNKNOWN_AS_TRUE. Collections.replaceAll(logicList, Logic.FALSE, Logic.UNKNOWN_AS_TRUE); } @Override public @Nullable Logic visitCall(RexCall call, @Nullable Logic logic) { final Logic arg0 = logic; switch (call.getKind()) { case IS_NOT_NULL: case IS_NULL: logic = Logic.TRUE_FALSE_UNKNOWN; break; case IS_TRUE: case IS_NOT_TRUE: logic = Logic.UNKNOWN_AS_FALSE; break; case IS_FALSE: case IS_NOT_FALSE: logic = Logic.UNKNOWN_AS_TRUE; break; case NOT: logic = requireNonNull(logic, "logic").negate2(); break; case CASE: logic = Logic.TRUE_FALSE_UNKNOWN; break; default: break; } switch (requireNonNull(logic, "logic")) { case TRUE: switch (call.getKind()) { case AND: break; default: logic = Logic.TRUE_FALSE_UNKNOWN; } break; default: break; } for (RexNode operand : call.operands) { operand.accept(this, logic); } return end(call, arg0); } @Override protected @Nullable Logic end(RexNode node, @Nullable Logic arg) { if (node.equals(seek)) { logicCollection.add(requireNonNull(arg, "arg")); } return arg; } @Override public @Nullable Logic visitOver(RexOver over, @Nullable Logic arg) { return end(over, arg); } @Override public @Nullable Logic visitFieldAccess(RexFieldAccess fieldAccess, @Nullable Logic arg) { return end(fieldAccess, arg); } @Override public @Nullable Logic visitSubQuery(RexSubQuery subQuery, @Nullable Logic arg) { if (!subQuery.getType().isNullable()) { if (arg == Logic.TRUE_FALSE_UNKNOWN) { arg = Logic.TRUE_FALSE; } } return end(subQuery, arg); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy