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

org.apache.calcite.rex.RexChecker Maven / Gradle / Ivy

There is a newer version: 1.17.0-flink-r3
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 org.apache.calcite.rex;

import org.apache.calcite.plan.RelOptUtil;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeField;
import org.apache.calcite.util.Litmus;

import java.util.List;

/**
 * Visitor which checks the validity of a {@link RexNode} expression.
 *
 * 

There are two modes of operation: * *

    *
  • Usefail=true to throw an {@link AssertionError} as soon as * an invalid node is detected: * *
    RexNode node;
    * RelDataType rowType;
    * assert new RexChecker(rowType, true).isValid(node);
    * * This mode requires that assertions are enabled.
  • * *
  • Use fail=false to test for validity without throwing an * error. * *
    RexNode node;
    * RelDataType rowType;
    * RexChecker checker = new RexChecker(rowType, false);
    * node.accept(checker);
    * if (!checker.valid) {
    *    ...
    * }
    *
  • *
* * @see RexNode */ public class RexChecker extends RexVisitorImpl { //~ Instance fields -------------------------------------------------------- protected final RelNode.Context context; protected final Litmus litmus; protected final List inputTypeList; protected int failCount; //~ Constructors ----------------------------------------------------------- /** * Creates a RexChecker with a given input row type. * *

If fail is true, the checker will throw an * {@link AssertionError} if an invalid node is found and assertions are * enabled. * *

Otherwise, each method returns whether its part of the tree is valid. * * @param inputRowType Input row type * @param context Context of the enclosing {@link RelNode}, or null * @param litmus What to do if an invalid node is detected */ public RexChecker(final RelDataType inputRowType, RelNode.Context context, Litmus litmus) { this(RelOptUtil.getFieldTypeList(inputRowType), context, litmus); } /** * Creates a RexChecker with a given set of input fields. * *

If fail is true, the checker will throw an * {@link AssertionError} if an invalid node is found and assertions are * enabled. * *

Otherwise, each method returns whether its part of the tree is valid. * * @param inputTypeList Input row type * @param context Context of the enclosing {@link RelNode}, or null * @param litmus What to do if an error is detected */ public RexChecker(List inputTypeList, RelNode.Context context, Litmus litmus) { super(true); this.inputTypeList = inputTypeList; this.context = context; this.litmus = litmus; } //~ Methods ---------------------------------------------------------------- /** * Returns the number of failures encountered. * * @return Number of failures */ public int getFailureCount() { return failCount; } @Override public Boolean visitInputRef(RexInputRef ref) { final int index = ref.getIndex(); if ((index < 0) || (index >= inputTypeList.size())) { ++failCount; return litmus.fail("RexInputRef index {} out of range 0..{}", index, inputTypeList.size() - 1); } if (!ref.getType().isStruct() && !RelOptUtil.eq("ref", ref.getType(), "input", inputTypeList.get(index), litmus)) { ++failCount; return litmus.fail(null); } return litmus.succeed(); } @Override public Boolean visitLocalRef(RexLocalRef ref) { ++failCount; return litmus.fail("RexLocalRef illegal outside program"); } @Override public Boolean visitCall(RexCall call) { for (RexNode operand : call.getOperands()) { Boolean valid = operand.accept(this); if (valid != null && !valid) { return litmus.fail(null); } } return litmus.succeed(); } @Override public Boolean visitFieldAccess(RexFieldAccess fieldAccess) { super.visitFieldAccess(fieldAccess); final RelDataType refType = fieldAccess.getReferenceExpr().getType(); assert refType.isStruct(); final RelDataTypeField field = fieldAccess.getField(); final int index = field.getIndex(); if ((index < 0) || (index > refType.getFieldList().size())) { ++failCount; return litmus.fail(null); } final RelDataTypeField typeField = refType.getFieldList().get(index); if (!RelOptUtil.eq( "type1", typeField.getType(), "type2", fieldAccess.getType(), litmus)) { ++failCount; return litmus.fail(null); } return litmus.succeed(); } @Override public Boolean visitCorrelVariable(RexCorrelVariable v) { if (context != null && !context.correlationIds().contains(v.id)) { ++failCount; return litmus.fail("correlation id {} not found in correlation list {}", v, context.correlationIds()); } return litmus.succeed(); } /** * Returns whether an expression is valid. */ public final boolean isValid(RexNode expr) { return expr.accept(this); } } // End RexChecker.java





© 2015 - 2024 Weber Informatics LLC | Privacy Policy