org.apache.hadoop.hive.ql.io.sarg.SearchArgument Maven / Gradle / Ivy
/*
* 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.hadoop.hive.ql.io.sarg;
import java.util.List;
/**
* Primary interface for
* SearchArgument, which are the subset of predicates
* that can be pushed down to the RecordReader. Each SearchArgument consists
* of a series of SearchClauses that must each be true for the row to be
* accepted by the filter.
*
* This requires that the filter be normalized into conjunctive normal form
* (CNF).
*/
public interface SearchArgument {
/**
* The potential result sets of logical operations.
*/
public static enum TruthValue {
YES, NO, NULL, YES_NULL, NO_NULL, YES_NO, YES_NO_NULL;
/**
* Compute logical or between the two values.
* @param right the other argument or null
* @return the result
*/
public TruthValue or(TruthValue right) {
if (right == null || right == this) {
return this;
}
if (right == YES || this == YES) {
return YES;
}
if (right == YES_NULL || this == YES_NULL) {
return YES_NULL;
}
if (right == NO) {
return this;
}
if (this == NO) {
return right;
}
if (this == NULL) {
if (right == NO_NULL) {
return NULL;
} else {
return YES_NULL;
}
}
if (right == NULL) {
if (this == NO_NULL) {
return NULL;
} else {
return YES_NULL;
}
}
return YES_NO_NULL;
}
/**
* Compute logical AND between the two values.
* @param right the other argument or null
* @return the result
*/
public TruthValue and(TruthValue right) {
if (right == null || right == this) {
return this;
}
if (right == NO || this == NO) {
return NO;
}
if (right == NO_NULL || this == NO_NULL) {
return NO_NULL;
}
if (right == YES) {
return this;
}
if (this == YES) {
return right;
}
if (this == NULL) {
if (right == YES_NULL) {
return NULL;
} else {
return NO_NULL;
}
}
if (right == NULL) {
if (this == YES_NULL) {
return NULL;
} else {
return NO_NULL;
}
}
return YES_NO_NULL;
}
public TruthValue not() {
switch (this) {
case NO:
return YES;
case YES:
return NO;
case NULL:
case YES_NO:
case YES_NO_NULL:
return this;
case NO_NULL:
return YES_NULL;
case YES_NULL:
return NO_NULL;
default:
throw new IllegalArgumentException("Unknown value: " + this);
}
}
/**
* Does the RecordReader need to include this set of records?
* @return true unless none of the rows qualify
*/
public boolean isNeeded() {
switch (this) {
case NO:
case NULL:
case NO_NULL:
return false;
default:
return true;
}
}
}
/**
* Get the leaf predicates that are required to evaluate the predicate. The
* list will have the duplicates removed.
* @return the list of leaf predicates
*/
public List getLeaves();
/**
* Get the expression tree. This should only needed for file formats that
* need to translate the expression to an internal form.
*/
public ExpressionTree getExpression();
/**
* Evaluate the entire predicate based on the values for the leaf predicates.
* @param leaves the value of each leaf predicate
* @return the value of hte entire predicate
*/
public TruthValue evaluate(TruthValue[] leaves);
/**
* A builder object for contexts outside of Hive where it isn't easy to
* get a ExprNodeDesc. The user must call startOr, startAnd, or startNot
* before adding any leaves.
*/
public interface Builder {
/**
* Start building an or operation and push it on the stack.
* @return this
*/
public Builder startOr();
/**
* Start building an and operation and push it on the stack.
* @return this
*/
public Builder startAnd();
/**
* Start building a not operation and push it on the stack.
* @return this
*/
public Builder startNot();
/**
* Finish the current operation and pop it off of the stack. Each start
* call must have a matching end.
* @return this
*/
public Builder end();
/**
* Add a less than leaf to the current item on the stack.
* @param column the name of the column
* @param type the type of the expression
* @param literal the literal
* @return this
*/
public Builder lessThan(String column, PredicateLeaf.Type type,
Object literal);
/**
* Add a less than equals leaf to the current item on the stack.
* @param column the name of the column
* @param type the type of the expression
* @param literal the literal
* @return this
*/
public Builder lessThanEquals(String column, PredicateLeaf.Type type,
Object literal);
/**
* Add an equals leaf to the current item on the stack.
* @param column the name of the column
* @param type the type of the expression
* @param literal the literal
* @return this
*/
public Builder equals(String column, PredicateLeaf.Type type,
Object literal);
/**
* Add a null safe equals leaf to the current item on the stack.
* @param column the name of the column
* @param type the type of the expression
* @param literal the literal
* @return this
*/
public Builder nullSafeEquals(String column, PredicateLeaf.Type type,
Object literal);
/**
* Add an in leaf to the current item on the stack.
* @param column the name of the column
* @param type the type of the expression
* @param literal the literal
* @return this
*/
public Builder in(String column, PredicateLeaf.Type type,
Object... literal);
/**
* Add an is null leaf to the current item on the stack.
* @param column the name of the column
* @param type the type of the expression
* @return this
*/
public Builder isNull(String column, PredicateLeaf.Type type);
/**
* Add a between leaf to the current item on the stack.
* @param column the name of the column
* @param type the type of the expression
* @param lower the literal
* @param upper the literal
* @return this
*/
public Builder between(String column, PredicateLeaf.Type type,
Object lower, Object upper);
/**
* Add a truth value to the expression.
* @param truth
* @return this
*/
public Builder literal(TruthValue truth);
/**
* Build and return the SearchArgument that has been defined. All of the
* starts must have been ended before this call.
* @return the new SearchArgument
*/
public SearchArgument build();
}
}