Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
CompoundPredicate.java
Go to the documentation of this file.
1 // Copyright 2012 Cloudera Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 package com.cloudera.impala.analysis;
16 
17 import java.util.ArrayList;
18 import java.util.List;
19 
25 import com.cloudera.impala.thrift.TExprNode;
26 import com.cloudera.impala.thrift.TExprNodeType;
27 import com.google.common.base.Objects;
28 import com.google.common.base.Preconditions;
29 import com.google.common.collect.Lists;
30 
35 public class CompoundPredicate extends Predicate {
36  public enum Operator {
37  AND("AND"),
38  OR("OR"),
39  NOT("NOT");
40 
41  private final String description;
42 
43  private Operator(String description) {
44  this.description = description;
45  }
46 
47  @Override
48  public String toString() {
49  return description;
50  }
51  }
52  private final Operator op_;
53 
54  public static void initBuiltins(Db db) {
55  // AND and OR are implemented as custom exprs, so they do not have a function symbol.
56  db.addBuiltin(ScalarFunction.createBuiltinOperator(
57  Operator.AND.name(), "",
58  Lists.<Type>newArrayList(Type.BOOLEAN, Type.BOOLEAN), Type.BOOLEAN));
59  db.addBuiltin(ScalarFunction.createBuiltinOperator(
60  Operator.OR.name(), "",
61  Lists.<Type>newArrayList(Type.BOOLEAN, Type.BOOLEAN), Type.BOOLEAN));
62  db.addBuiltin(ScalarFunction.createBuiltinOperator(
63  Operator.NOT.name(), "impala::CompoundPredicate::Not",
64  Lists.<Type>newArrayList(Type.BOOLEAN), Type.BOOLEAN));
65  }
66 
67  public CompoundPredicate(Operator op, Expr e1, Expr e2) {
68  super();
69  this.op_ = op;
70  Preconditions.checkNotNull(e1);
71  children_.add(e1);
72  Preconditions.checkArgument(op == Operator.NOT && e2 == null
73  || op != Operator.NOT && e2 != null);
74  if (e2 != null) children_.add(e2);
75  }
76 
81  super(other);
82  op_ = other.op_;
83  }
84 
85  public Operator getOp() { return op_; }
86 
87  @Override
88  public boolean equals(Object obj) {
89  if (!super.equals(obj)) return false;
90  return ((CompoundPredicate) obj).op_ == op_;
91  }
92 
93  @Override
94  public String debugString() {
95  return Objects.toStringHelper(this)
96  .add("op", op_)
97  .addValue(super.debugString())
98  .toString();
99  }
100 
101  @Override
102  public String toSqlImpl() {
103  if (children_.size() == 1) {
104  Preconditions.checkState(op_ == Operator.NOT);
105  return "NOT " + getChild(0).toSql();
106  } else {
107  return getChild(0).toSql() + " " + op_.toString() + " " + getChild(1).toSql();
108  }
109  }
110 
111  @Override
112  protected void toThrift(TExprNode msg) {
113  msg.node_type = TExprNodeType.COMPOUND_PRED;
114  }
115 
116  @Override
117  public void analyze(Analyzer analyzer) throws AnalysisException {
118  if (isAnalyzed_) return;
119  super.analyze(analyzer);
120 
121  // Check that children are predicates.
122  for (Expr e: children_) {
123  if (!e.getType().isBoolean() && !e.getType().isNull()) {
124  throw new AnalysisException(String.format("Operand '%s' part of predicate " +
125  "'%s' should return type 'BOOLEAN' but returns type '%s'.",
126  e.toSql(), toSql(), e.getType().toSql()));
127  }
128  }
129 
132  Preconditions.checkState(fn_ != null);
133  Preconditions.checkState(fn_.getReturnType().isBoolean());
134  castForFunctionCall(false);
135 
136  if (getChild(0).selectivity_ == -1
137  || children_.size() == 2 && getChild(1).selectivity_ == -1) {
138  // give up if we're missing an input
139  selectivity_ = -1;
140  return;
141  }
142 
143  switch (op_) {
144  case AND:
145  selectivity_ = getChild(0).selectivity_ * getChild(1).selectivity_;
146  break;
147  case OR:
148  selectivity_ = getChild(0).selectivity_ + getChild(1).selectivity_
149  - getChild(0).selectivity_ * getChild(1).selectivity_;
150  break;
151  case NOT:
152  selectivity_ = 1.0 - getChild(0).selectivity_;
153  break;
154  }
155  selectivity_ = Math.max(0.0, Math.min(1.0, selectivity_));
156  }
157 
162  public ArrayList<SlotRef> getBoundSlots() {
163  ArrayList<SlotRef> slots = Lists.newArrayList();
164  for (int i = 0; i < getChildren().size(); ++i) {
165  if (getChild(i) instanceof BinaryPredicate ||
166  getChild(i) instanceof InPredicate) {
167  slots.add(((Predicate)getChild(i)).getBoundSlot());
168  } else if (getChild(i) instanceof CompoundPredicate) {
169  slots.addAll(((CompoundPredicate)getChild(i)).getBoundSlots());
170  }
171  }
172  return slots;
173  }
174 
178  @Override
179  public Expr negate() {
180  if (op_ == Operator.NOT) return getChild(0);
181  Expr negatedLeft = getChild(0).negate();
182  Expr negatedRight = getChild(1).negate();
183  Operator newOp = (op_ == Operator.OR) ? Operator.AND : Operator.OR;
184  return new CompoundPredicate(newOp, negatedLeft, negatedRight);
185  }
186 
190  public static Expr createConjunctivePredicate(List<Expr> conjuncts) {
191  Expr conjunctivePred = null;
192  for (Expr expr: conjuncts) {
193  if (conjunctivePred == null) {
194  conjunctivePred = expr;
195  continue;
196  }
197  conjunctivePred = new CompoundPredicate(CompoundPredicate.Operator.AND,
198  expr, conjunctivePred);
199  }
200  return conjunctivePred;
201  }
202 
203  @Override
204  public Expr clone() { return new CompoundPredicate(this); }
205 
206  // Create an AND predicate between two exprs, 'lhs' and 'rhs'. If
207  // 'rhs' is null, simply return 'lhs'.
208  public static Expr createConjunction(Expr lhs, Expr rhs) {
209  if (rhs == null) return lhs;
210  return new CompoundPredicate(Operator.AND, rhs, lhs);
211  }
212 }
void castForFunctionCall(boolean ignoreWildcardDecimals)
Definition: Expr.java:312
static final ScalarType BOOLEAN
Definition: Type.java:46
static Expr createConjunction(Expr lhs, Expr rhs)
CompoundPredicate(Operator op, Expr e1, Expr e2)
Function getBuiltinFunction(Analyzer analyzer, String name, Type[] argTypes, CompareMode mode)
Definition: Expr.java:290
static Expr createConjunctivePredicate(List< Expr > conjuncts)