| /* |
| * 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; |
| |
| /** Policy for whether a simplified expression may instead return another |
| * value. |
| * |
| * <p>In particular, it deals with converting three-valued logic (TRUE, FALSE, |
| * UNKNOWN) to two-valued logic (TRUE, FALSE) for callers that treat the UNKNOWN |
| * value the same as TRUE or FALSE. |
| * |
| * <p>Sometimes the three-valued version of the expression is simpler (has a |
| * smaller expression tree) than the two-valued version. In these cases, |
| * favor simplicity over reduction to two-valued logic. |
| * |
| * @see RexSimplify */ |
| public enum RexUnknownAs { |
| /** Policy that indicates that the expression is being used in a context |
| * Where an UNKNOWN value is treated in the same way as FALSE. Therefore, when |
| * simplifying the expression, it is acceptable for the simplified expression |
| * to evaluate to FALSE in some situations where the original expression would |
| * evaluate to UNKNOWN. |
| * |
| * <p>SQL predicates ({@code WHERE}, {@code ON}, {@code HAVING} and |
| * {@code FILTER (WHERE)} clauses, a {@code WHEN} clause of a {@code CASE} |
| * expression, and in {@code CHECK} constraints) all treat UNKNOWN as FALSE. |
| * |
| * <p>If the simplified expression never returns UNKNOWN, the simplifier |
| * should make this clear to the caller, if possible, by marking its type as |
| * {@code BOOLEAN NOT NULL}. */ |
| FALSE, |
| |
| /** Policy that indicates that the expression is being used in a context |
| * Where an UNKNOWN value is treated in the same way as TRUE. Therefore, when |
| * simplifying the expression, it is acceptable for the simplified expression |
| * to evaluate to TRUE in some situations where the original expression would |
| * evaluate to UNKNOWN. |
| * |
| * <p>This does not occur commonly in SQL. However, it occurs internally |
| * during simplification. For example, "{@code WHERE NOT expression}" |
| * evaluates "{@code NOT expression}" in a context that treats UNKNOWN as |
| * FALSE; it is useful to consider that "{@code expression}" is evaluated in a |
| * context that treats UNKNOWN as TRUE. |
| * |
| * <p>If the simplified expression never returns UNKNOWN, the simplifier |
| * should make this clear to the caller, if possible, by marking its type as |
| * {@code BOOLEAN NOT NULL}. */ |
| TRUE, |
| |
| /** Policy that indicates that the expression is being used in a context |
| * Where an UNKNOWN value is treated as is. This occurs: |
| * |
| * <ul> |
| * <li>In any expression whose type is not {@code BOOLEAN} |
| * <li>In {@code BOOLEAN} expressions that are {@code NOT NULL} |
| * <li>In {@code BOOLEAN} expressions where {@code UNKNOWN} should be |
| * returned as is, for example in a {@code SELECT} clause, or within an |
| * expression such as an operand to {@code AND}, {@code OR} or |
| * {@code NOT} |
| * </ul> |
| * |
| * <p>If you are unsure, use UNKNOWN. It is the safest option. */ |
| UNKNOWN; |
| |
| /** Returns {@link #FALSE} if {@code unknownAsFalse} is true, |
| * {@link #UNKNOWN} otherwise. */ |
| public static RexUnknownAs falseIf(boolean unknownAsFalse) { |
| return unknownAsFalse ? FALSE : UNKNOWN; |
| } |
| |
| public boolean toBoolean() { |
| switch (this) { |
| case FALSE: |
| return false; |
| case TRUE: |
| return true; |
| default: |
| throw new IllegalArgumentException("unknown"); |
| } |
| } |
| |
| public RexUnknownAs negate() { |
| switch (this) { |
| case TRUE: |
| return FALSE; |
| case FALSE: |
| return TRUE; |
| default: |
| return UNKNOWN; |
| } |
| } |
| |
| /** Combines this with another {@code RexUnknownAs} in the same way as the |
| * three-valued logic of OR. |
| * |
| * <p>For example, {@code TRUE or FALSE} returns {@code TRUE}; |
| * {@code FALSE or UNKNOWN} returns {@code UNKNOWN}. */ |
| public RexUnknownAs or(RexUnknownAs other) { |
| switch (this) { |
| case TRUE: |
| return this; |
| case UNKNOWN: |
| return other == TRUE ? other : this; |
| case FALSE: |
| default: |
| return other; |
| } |
| } |
| } |