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

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

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

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

import java.util.ArrayList;
import java.util.List;

import static java.util.Objects.requireNonNull;

/**
 * Passes over a row-expression, calling a handler method for each node,
 * appropriate to the type of the node.
 *
 * 

Like {@link RexVisitor}, this is an instance of the * {@link com.hazelcast.org.apache.calcite.util.Glossary#VISITOR_PATTERN Visitor Pattern}. Use * RexShuttle if you would like your methods to return a * value.

*/ public class RexShuttle implements RexVisitor { //~ Methods ---------------------------------------------------------------- @Override public RexNode visitOver(RexOver over) { boolean[] update = {false}; List clonedOperands = visitList(over.operands, update); RexWindow window = visitWindow(over.getWindow()); if (update[0] || (window != over.getWindow())) { // REVIEW jvs 8-Mar-2005: This doesn't take into account // the fact that a rewrite may have changed the result type. // To do that, we would need to take a RexBuilder and // watch out for special operators like CAST and NEW where // the type is embedded in the original call. return new RexOver( over.getType(), over.getAggOperator(), clonedOperands, window, over.isDistinct(), over.ignoreNulls()); } else { return over; } } public RexWindow visitWindow(RexWindow window) { boolean[] update = {false}; List clonedOrderKeys = visitFieldCollations(window.orderKeys, update); List clonedPartitionKeys = visitList(window.partitionKeys, update); final RexWindowBound lowerBound = window.getLowerBound().accept(this); final RexWindowBound upperBound = window.getUpperBound().accept(this); if (lowerBound == null || upperBound == null || !update[0] && lowerBound == window.getLowerBound() && upperBound == window.getUpperBound()) { return window; } boolean rows = window.isRows(); if (lowerBound.isUnbounded() && lowerBound.isPreceding() && upperBound.isUnbounded() && upperBound.isFollowing()) { // RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING // is equivalent to // ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING // but we prefer "RANGE" rows = false; } return new RexWindow( clonedPartitionKeys, clonedOrderKeys, lowerBound, upperBound, rows); } @Override public RexNode visitSubQuery(RexSubQuery subQuery) { boolean[] update = {false}; List clonedOperands = visitList(subQuery.operands, update); if (update[0]) { return subQuery.clone(subQuery.getType(), clonedOperands); } else { return subQuery; } } @Override public RexNode visitTableInputRef(RexTableInputRef ref) { return ref; } @Override public RexNode visitPatternFieldRef(RexPatternFieldRef fieldRef) { return fieldRef; } @Override public RexNode visitCall(final RexCall call) { boolean[] update = {false}; List clonedOperands = visitList(call.operands, update); if (update[0]) { // REVIEW jvs 8-Mar-2005: This doesn't take into account // the fact that a rewrite may have changed the result type. // To do that, we would need to take a RexBuilder and // watch out for special operators like CAST and NEW where // the type is embedded in the original call. return call.clone(call.getType(), clonedOperands); } else { return call; } } /** * Visits each of an array of expressions and returns an array of the * results. * * @param exprs Array of expressions * @param update If not null, sets this to true if any of the expressions * was modified * @return Array of visited expressions */ protected RexNode[] visitArray(RexNode[] exprs, boolean @Nullable [] update) { RexNode[] clonedOperands = new RexNode[exprs.length]; for (int i = 0; i < exprs.length; i++) { RexNode operand = exprs[i]; RexNode clonedOperand = operand.accept(this); if ((clonedOperand != operand) && (update != null)) { update[0] = true; } clonedOperands[i] = clonedOperand; } return clonedOperands; } /** * Visits each of a list of expressions and returns a list of the * results. * * @param exprs List of expressions * @param update If not null, sets this to true if any of the expressions * was modified * @return Array of visited expressions */ protected List visitList( List exprs, boolean @Nullable [] update) { ImmutableList.Builder clonedOperands = ImmutableList.builder(); for (RexNode operand : exprs) { RexNode clonedOperand = operand.accept(this); if ((clonedOperand != operand) && (update != null)) { update[0] = true; } clonedOperands.add(clonedOperand); } return clonedOperands.build(); } /** * Visits each of a list of field collations and returns a list of the * results. * * @param collations List of field collations * @param update If not null, sets this to true if any of the expressions * was modified * @return Array of visited field collations */ protected List visitFieldCollations( List collations, boolean @Nullable [] update) { ImmutableList.Builder clonedOperands = ImmutableList.builder(); for (RexFieldCollation collation : collations) { RexNode clonedOperand = collation.left.accept(this); if ((clonedOperand != collation.left) && (update != null)) { update[0] = true; collation = new RexFieldCollation(clonedOperand, requireNonNull(collation.right)); } clonedOperands.add(collation); } return clonedOperands.build(); } @Override public RexNode visitCorrelVariable(RexCorrelVariable variable) { return variable; } @Override public RexNode visitFieldAccess(RexFieldAccess fieldAccess) { RexNode before = fieldAccess.getReferenceExpr(); RexNode after = before.accept(this); if (before == after) { return fieldAccess; } else { return new RexFieldAccess( after, fieldAccess.getField()); } } @Override public RexNode visitInputRef(RexInputRef inputRef) { return inputRef; } @Override public RexNode visitLocalRef(RexLocalRef localRef) { return localRef; } @Override public RexNode visitLiteral(RexLiteral literal) { return literal; } @Override public RexNode visitDynamicParam(RexDynamicParam dynamicParam) { return dynamicParam; } @Override public RexNode visitRangeRef(RexRangeRef rangeRef) { return rangeRef; } /** * Applies this shuttle to each expression in a list. * * @return whether any of the expressions changed */ public final boolean mutate(List exprList) { int changeCount = 0; for (int i = 0; i < exprList.size(); i++) { T expr = exprList.get(i); T expr2 = (T) apply(expr); // Avoid NPE if expr is null if (expr != expr2) { ++changeCount; exprList.set(i, expr2); } } return changeCount > 0; } /** * Applies this shuttle to each expression in a list and returns the * resulting list. Does not modify the initial list. * *

Returns null if and only if {@code exprList} is null. */ public final @PolyNull List apply(@PolyNull List exprList) { if (exprList == null) { return exprList; } final List list2 = new ArrayList<>(exprList); if (mutate(list2)) { return list2; } else { return exprList; } } /** * Applies this shuttle to an expression, or returns null if the expression * is null. */ public final @PolyNull RexNode apply(@PolyNull RexNode expr) { return (expr == null) ? expr : expr.accept(this); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy