Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
IsNullPredicate.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 
25 import com.cloudera.impala.common.Reference;
26 import com.cloudera.impala.thrift.TExprNode;
27 import com.cloudera.impala.thrift.TExprNodeType;
28 import com.google.common.base.Objects;
29 import com.google.common.base.Preconditions;
30 import com.google.common.collect.Lists;
31 
32 public class IsNullPredicate extends Predicate {
33  private final boolean isNotNull_;
34 
35  private static final String IS_NULL = "is_null_pred";
36  private static final String IS_NOT_NULL = "is_not_null_pred";
37 
38  public IsNullPredicate(Expr e, boolean isNotNull) {
39  super();
40  this.isNotNull_ = isNotNull;
41  Preconditions.checkNotNull(e);
42  children_.add(e);
43  }
44 
48  protected IsNullPredicate(IsNullPredicate other) {
49  super(other);
50  isNotNull_ = other.isNotNull_;
51  }
52 
53  public boolean isNotNull() { return isNotNull_; }
54 
55  public static void initBuiltins(Db db) {
56  for (Type t: Type.getSupportedTypes()) {
57  if (t.isNull()) continue;
58  String isNullSymbol;
59  if (t.isBoolean()) {
60  isNullSymbol = "_ZN6impala15IsNullPredicate6IsNullIN10impala_udf10BooleanValE" +
61  "EES3_PNS2_15FunctionContextERKT_";
62  } else {
63  String udfType = Function.getUdfType(t);
64  isNullSymbol = "_ZN6impala15IsNullPredicate6IsNullIN10impala_udf" +
65  udfType.length() + udfType +
66  "EEENS2_10BooleanValEPNS2_15FunctionContextERKT_";
67  }
68  db.addBuiltin(ScalarFunction.createBuiltinOperator(
69  IS_NULL, isNullSymbol, Lists.newArrayList(t), Type.BOOLEAN));
70 
71  String isNotNullSymbol = isNullSymbol.replace("6IsNull", "9IsNotNull");
72  db.addBuiltin(ScalarFunction.createBuiltinOperator(
73  IS_NOT_NULL, isNotNullSymbol, Lists.newArrayList(t), Type.BOOLEAN));
74  }
75  }
76 
77  @Override
78  public boolean equals(Object obj) {
79  if (!super.equals(obj)) return false;
80  return ((IsNullPredicate) obj).isNotNull_ == isNotNull_;
81  }
82 
83  @Override
84  public String toSqlImpl() {
85  return getChild(0).toSql() + (isNotNull_ ? " IS NOT NULL" : " IS NULL");
86  }
87 
88  @Override
89  public String debugString() {
90  return Objects.toStringHelper(this)
91  .add("notNull", isNotNull_)
92  .addValue(super.debugString())
93  .toString();
94  }
95 
96  @Override
97  public void analyze(Analyzer analyzer) throws AnalysisException {
98  if (isAnalyzed_) return;
99  super.analyze(analyzer);
100 
101  if (contains(Subquery.class)) {
102  if (getChild(0) instanceof ExistsPredicate) {
103  // Replace the EXISTS subquery with a BoolLiteral as it can never return
104  // a null value.
105  setChild(0, new BoolLiteral(true));
106  getChild(0).analyze(analyzer);
107  } else if (!getChild(0).contains(Expr.IS_SCALAR_SUBQUERY)) {
108  // We only support scalar subqueries in an IS NULL predicate because
109  // they can be rewritten into a join.
110  // TODO: Add support for InPredicates and BinaryPredicates with
111  // subqueries when we implement independent subquery evaluation.
112  // TODO: Handle arbitrary UDA/Udfs
113  throw new AnalysisException("Unsupported IS NULL predicate that contains " +
114  "a subquery: " + toSqlImpl());
115  }
116  }
117 
118  // Make sure the BE never sees TYPE_NULL
119  if (getChild(0).getType().isNull()) {
121  }
122 
123  if (isNotNull_) {
126  } else {
129  }
130 
131  // determine selectivity
132  // TODO: increase this to make sure we don't end up favoring broadcast joins
133  // due to underestimated cardinalities?
135  Reference<SlotRef> slotRefRef = new Reference<SlotRef>();
136  if (isSingleColumnPredicate(slotRefRef, null)) {
137  SlotDescriptor slotDesc = slotRefRef.getRef().getDesc();
138  if (!slotDesc.getStats().hasNulls()) return;
139  Table table = slotDesc.getParent().getTable();
140  if (table != null && table.getNumRows() > 0) {
141  long numRows = table.getNumRows();
142  if (isNotNull_) {
143  selectivity_ =
144  (double) (numRows - slotDesc.getStats().getNumNulls()) / (double) numRows;
145  } else {
146  selectivity_ = (double) slotDesc.getStats().getNumNulls() / (double) numRows;
147  }
148  selectivity_ = Math.max(0.0, Math.min(1.0, selectivity_));
149  }
150  }
151  }
152 
153  @Override
154  protected void toThrift(TExprNode msg) {
155  msg.node_type = TExprNodeType.FUNCTION_CALL;
156  }
157 
158  /*
159  * If predicate is of the form "<SlotRef> IS [NOT] NULL", returns the
160  * SlotRef.
161  */
162  @Override
164  return getChild(0).unwrapSlotRef(true);
165  }
166 
170  @Override
171  public Expr negate() {
172  return new IsNullPredicate(getChild(0), !isNotNull_);
173  }
174 
175  @Override
176  public Expr clone() { return new IsNullPredicate(this); }
177 }
void uncheckedCastChild(Type targetType, int childIndex)
Definition: Expr.java:1024
static final ScalarType BOOLEAN
Definition: Type.java:46
Function getBuiltinFunction(Analyzer analyzer, String name, Type[] argTypes, CompareMode mode)
Definition: Expr.java:290
boolean isSingleColumnPredicate(Reference< SlotRef > slotRefRef, Reference< Integer > idxRef)
Definition: Predicate.java:64
static final com.google.common.base.Predicate< Expr > IS_SCALAR_SUBQUERY
Definition: Expr.java:95
static ArrayList< ScalarType > getSupportedTypes()
Definition: Type.java:109
static double DEFAULT_SELECTIVITY
Definition: Expr.java:63