Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
BetweenPredicate.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 
21 import com.cloudera.impala.thrift.TExprNode;
22 import com.google.common.base.Preconditions;
23 import com.google.common.collect.Lists;
24 
30 public class BetweenPredicate extends Predicate {
31 
32  private final boolean isNotBetween_;
33 
34  // After successful analysis, we rewrite this between predicate
35  // into a conjunctive/disjunctive compound predicate.
37 
38  // Children of the BetweenPredicate, since this.children should hold the children
39  // of the rewritten predicate to make sure toThrift() picks up the right ones.
40  private ArrayList<Expr> originalChildren_ = Lists.newArrayList();
41 
42  // First child is the comparison expr which should be in [lowerBound, upperBound].
43  public BetweenPredicate(Expr compareExpr, Expr lowerBound, Expr upperBound,
44  boolean isNotBetween) {
45  originalChildren_.add(compareExpr);
46  originalChildren_.add(lowerBound);
47  originalChildren_.add(upperBound);
48  this.isNotBetween_ = isNotBetween;
49  }
50 
55  super(other);
56  isNotBetween_ = other.isNotBetween_;
57  originalChildren_ = Expr.cloneList(other.originalChildren_);
58  if (other.rewrittenPredicate_ != null) {
60  }
61  }
62 
64  Preconditions.checkState(isAnalyzed_);
65  return rewrittenPredicate_;
66  }
67 
68  @Override
69  public void analyze(Analyzer analyzer) throws AnalysisException {
70  if (isAnalyzed_) return;
71  super.analyze(analyzer);
72  if (originalChildren_.get(0) instanceof Subquery &&
73  (originalChildren_.get(1) instanceof Subquery ||
74  originalChildren_.get(2) instanceof Subquery)) {
75  throw new AnalysisException("Comparison between subqueries is not " +
76  "supported in a between predicate: " + toSqlImpl());
77  }
78  analyzer.castAllToCompatibleType(originalChildren_);
79  // TODO: improve with histograms
81 
82  // Rewrite between predicate into a conjunctive/disjunctive compound predicate.
83  if (isNotBetween_) {
84  // Rewrite into disjunction.
85  Predicate lower = new BinaryPredicate(BinaryPredicate.Operator.LT,
86  originalChildren_.get(0), originalChildren_.get(1));
87  Predicate upper = new BinaryPredicate(BinaryPredicate.Operator.GT,
88  originalChildren_.get(0), originalChildren_.get(2));
90  new CompoundPredicate(CompoundPredicate.Operator.OR, lower, upper);
91  } else {
92  // Rewrite into conjunction.
93  Predicate lower = new BinaryPredicate(BinaryPredicate.Operator.GE,
94  originalChildren_.get(0), originalChildren_.get(1));
95  Predicate upper = new BinaryPredicate(BinaryPredicate.Operator.LE,
96  originalChildren_.get(0), originalChildren_.get(2));
98  new CompoundPredicate(CompoundPredicate.Operator.AND, lower, upper);
99  }
100 
101  try {
102  rewrittenPredicate_.analyze(analyzer);
103  fn_ = rewrittenPredicate_.fn_;
104  } catch (AnalysisException e) {
105  // We should have already guaranteed that analysis will succeed.
106  Preconditions.checkState(false, "Analysis failed in rewritten between predicate");
107  }
108 
109  // Make sure toThrift() picks up the children of the rewritten predicate.
110  children_ = rewrittenPredicate_.getChildren();
111  isAnalyzed_ = true;
112  }
113 
114  @Override
115  public List<Expr> getConjuncts() {
116  return rewrittenPredicate_.getConjuncts();
117  }
118 
119  @Override
120  protected void toThrift(TExprNode msg) {
121  rewrittenPredicate_.toThrift(msg);
122  }
123 
124  @Override
125  public String toSqlImpl() {
126  String notStr = (isNotBetween_) ? "NOT " : "";
127  return originalChildren_.get(0).toSql() + " " + notStr + "BETWEEN " +
128  originalChildren_.get(1).toSql() + " AND " + originalChildren_.get(2).toSql();
129  }
130 
134  @Override
136  throws AnalysisException {
137  BetweenPredicate clone = (BetweenPredicate) super.substituteImpl(smap, analyzer);
138  Preconditions.checkNotNull(clone);
139  clone.originalChildren_ =
140  Expr.substituteList(originalChildren_, smap, analyzer, false);
141  return clone;
142  }
143 
144  @Override
145  public Expr clone() { return new BetweenPredicate(this); }
146 
147  @Override
148  public Expr reset() {
149  super.reset();
150  originalChildren_ = Expr.resetList(originalChildren_);
151  return this;
152  }
153 }
BetweenPredicate(Expr compareExpr, Expr lowerBound, Expr upperBound, boolean isNotBetween)
Expr substituteImpl(ExprSubstitutionMap smap, Analyzer analyzer)
Expr substituteImpl(ExprSubstitutionMap smap, Analyzer analyzer)
Definition: Expr.java:745
static double DEFAULT_SELECTIVITY
Definition: Expr.java:63