Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
LikePredicate.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.regex.Pattern;
18 import java.util.regex.PatternSyntaxException;
19 
25 import com.cloudera.impala.thrift.TExprNode;
26 import com.cloudera.impala.thrift.TExprNodeType;
27 import com.google.common.base.Preconditions;
28 import com.google.common.collect.Lists;
29 
30 public class LikePredicate extends Predicate {
31  enum Operator {
32  LIKE("LIKE"),
33  RLIKE("RLIKE"),
34  REGEXP("REGEXP");
35 
36  private final String description_;
37 
38  private Operator(String description) {
39  this.description_ = description;
40  }
41 
42  @Override
43  public String toString() {
44  return description_;
45  }
46  }
47 
48  public static void initBuiltins(Db db) {
49  db.addBuiltin(ScalarFunction.createBuiltin(
50  Operator.LIKE.name(), Lists.<Type>newArrayList(Type.STRING, Type.STRING),
51  false, Type.BOOLEAN, "_ZN6impala13LikePredicate4LikeEPN10impala_udf15FunctionContextERKNS1_9StringValES6_", "_ZN6impala13LikePredicate11LikePrepareEPN10impala_udf15FunctionContextENS2_18FunctionStateScopeE",
52  "_ZN6impala13LikePredicate9LikeCloseEPN10impala_udf15FunctionContextENS2_18FunctionStateScopeE", true));
53  db.addBuiltin(ScalarFunction.createBuiltin(
54  Operator.RLIKE.name(), Lists.<Type>newArrayList(Type.STRING, Type.STRING),
55  false, Type.BOOLEAN, "_ZN6impala13LikePredicate5RegexEPN10impala_udf15FunctionContextERKNS1_9StringValES6_", "_ZN6impala13LikePredicate12RegexPrepareEPN10impala_udf15FunctionContextENS2_18FunctionStateScopeE",
56  "_ZN6impala13LikePredicate10RegexCloseEPN10impala_udf15FunctionContextENS2_18FunctionStateScopeE", true));
57  db.addBuiltin(ScalarFunction.createBuiltin(
58  Operator.REGEXP.name(), Lists.<Type>newArrayList(Type.STRING, Type.STRING),
59  false, Type.BOOLEAN, "_ZN6impala13LikePredicate5RegexEPN10impala_udf15FunctionContextERKNS1_9StringValES6_", "_ZN6impala13LikePredicate12RegexPrepareEPN10impala_udf15FunctionContextENS2_18FunctionStateScopeE",
60  "_ZN6impala13LikePredicate10RegexCloseEPN10impala_udf15FunctionContextENS2_18FunctionStateScopeE", true));
61  }
62 
63  private final Operator op_;
64 
65  public LikePredicate(Operator op, Expr e1, Expr e2) {
66  super();
67  this.op_ = op;
68  Preconditions.checkNotNull(e1);
69  children_.add(e1);
70  Preconditions.checkNotNull(e2);
71  children_.add(e2);
72  // TODO: improve with histograms?
73  selectivity_ = 0.1;
74  }
75 
79  public LikePredicate(LikePredicate other) {
80  super(other);
81  op_ = other.op_;
82  }
83 
84  @Override
85  public boolean equals(Object obj) {
86  if (!super.equals(obj)) return false;
87  return ((LikePredicate) obj).op_ == op_;
88  }
89 
90  @Override
91  public String toSqlImpl() {
92  return getChild(0).toSql() + " " + op_.toString() + " " + getChild(1).toSql();
93  }
94 
95  @Override
96  protected void toThrift(TExprNode msg) {
97  msg.node_type = TExprNodeType.FUNCTION_CALL;
98  }
99 
100  @Override
101  public void analyze(Analyzer analyzer) throws AnalysisException {
102  if (isAnalyzed_) return;
103  super.analyze(analyzer);
104  if (!getChild(0).getType().isStringType() && !getChild(0).getType().isNull()) {
105  throw new AnalysisException(
106  "left operand of " + op_.toString() + " must be of type STRING: " + toSql());
107  }
108  if (!getChild(1).getType().isStringType() && !getChild(1).getType().isNull()) {
109  throw new AnalysisException(
110  "right operand of " + op_.toString() + " must be of type STRING: " + toSql());
111  }
112 
115  Preconditions.checkState(fn_ != null);
116  Preconditions.checkState(fn_.getReturnType().isBoolean());
117 
118  if (getChild(1).isLiteral() && !getChild(1).isNullLiteral()
119  && (op_ == Operator.RLIKE || op_ == Operator.REGEXP)) {
120  // let's make sure the pattern works
121  // TODO: this checks that it's a Java-supported regex, but the syntax supported
122  // by the backend is Posix; add a call to the backend to check the re syntax
123  try {
124  Pattern.compile(((StringLiteral) getChild(1)).getValue());
125  } catch (PatternSyntaxException e) {
126  throw new AnalysisException(
127  "invalid regular expression in '" + this.toSql() + "'");
128  }
129  }
130  castForFunctionCall(false);
131  }
132 
133  @Override
134  public Expr clone() { return new LikePredicate(this); }
135 }
void castForFunctionCall(boolean ignoreWildcardDecimals)
Definition: Expr.java:312
static final ScalarType STRING
Definition: Type.java:53
static final ScalarType BOOLEAN
Definition: Type.java:46
LikePredicate(Operator op, Expr e1, Expr e2)
Function getBuiltinFunction(Analyzer analyzer, String name, Type[] argTypes, CompareMode mode)
Definition: Expr.java:290