Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
in-predicate-ir.cc
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 #include <sstream>
16 
17 #include "exprs/in-predicate.h"
18 
19 #include "exprs/anyval-util.h"
21 
22 #include "common/names.h"
23 
24 using namespace impala_udf;
25 
26 namespace impala {
27 
28 // Templated getter functions for extracting 'SetType' values from AnyVals
29 template<typename T, typename SetType>
30 SetType GetVal(const FunctionContext::TypeDesc* type, const T& x) {
31  DCHECK(!x.is_null);
32  return x.val;
33 }
34 
35 template<> StringValue GetVal(const FunctionContext::TypeDesc* type, const StringVal& x) {
36  DCHECK(!x.is_null);
37  return StringValue::FromStringVal(x);
38 }
39 
41  const FunctionContext::TypeDesc* type, const TimestampVal& x) {
42  return TimestampValue::FromTimestampVal(x);
43 }
44 
46  const FunctionContext::TypeDesc* type, const DecimalVal& x) {
47  if (type->precision <= ColumnType::MAX_DECIMAL4_PRECISION) {
48  return Decimal16Value(x.val4);
49  } else if (type->precision <= ColumnType::MAX_DECIMAL8_PRECISION) {
50  return Decimal16Value(x.val8);
51  } else {
52  return Decimal16Value(x.val16);
53  }
54 }
55 
56 template<typename T, typename SetType>
57 void InPredicate::SetLookupPrepare(
59  if (scope != FunctionContext::FRAGMENT_LOCAL) return;
60 
62  state->type = ctx->GetArgType(0);
63  state->contains_null = false;
64  for (int i = 1; i < ctx->GetNumArgs(); ++i) {
65  DCHECK(ctx->IsArgConstant(i));
66  T* arg = reinterpret_cast<T*>(ctx->GetConstantArg(i));
67  if (arg->is_null) {
68  state->contains_null = true;
69  } else {
70  state->val_set.insert(GetVal<T, SetType>(state->type, *arg));
71  }
72  }
73  ctx->SetFunctionState(scope, state);
74 }
75 
76 template<typename SetType>
77 void InPredicate::SetLookupClose(
79  if (scope != FunctionContext::FRAGMENT_LOCAL) return;
81  reinterpret_cast<SetLookupState<SetType>*>(ctx->GetFunctionState(scope));
82  delete state;
83 }
84 
85 template<typename T, typename SetType, bool not_in, InPredicate::Strategy strategy>
86 BooleanVal InPredicate::TemplatedIn(
87  FunctionContext* ctx, const T& val, int num_args, const T* args) {
88  if (val.is_null) return BooleanVal::null();
89 
90  BooleanVal found;
91  if (strategy == SET_LOOKUP) {
92  SetLookupState<SetType>* state = reinterpret_cast<SetLookupState<SetType>*>(
94  DCHECK_NOTNULL(state);
95  found = SetLookup(state, val);
96  } else {
97  DCHECK_EQ(strategy, ITERATE);
98  found = Iterate(ctx->GetArgType(0), val, num_args, args);
99  }
100  if (found.is_null) return BooleanVal::null();
101  return BooleanVal(found.val ^ not_in);
102 }
103 
104 template<typename T, typename SetType>
105 BooleanVal InPredicate::SetLookup(
106  SetLookupState<SetType>* state, const T& v) {
107  DCHECK_NOTNULL(state);
108  SetType val = GetVal<T, SetType>(state->type, v);
109  bool found = state->val_set.find(val) != state->val_set.end();
110  if (found) return BooleanVal(true);
111  if (state->contains_null) return BooleanVal::null();
112  return BooleanVal(false);
113 }
114 
115 template<typename T>
116 BooleanVal InPredicate::Iterate(
117  const FunctionContext::TypeDesc* type, const T& val, int num_args, const T* args) {
118  bool found_null = false;
119  for (int i = 0; i < num_args; ++i) {
120  if (args[i].is_null) {
121  found_null = true;
122  } else if (AnyValUtil::Equals(type, val, args[i])) {
123  return BooleanVal(true);
124  }
125  }
126  if (found_null) return BooleanVal::null();
127  return BooleanVal(false);
128 }
129 
130 #define IN_FUNCTIONS(AnyValType, SetType, type_name) \
131  BooleanVal InPredicate::InSetLookup( \
132  FunctionContext* context, const AnyValType& val, int num_args, \
133  const AnyValType* args) { \
134  return TemplatedIn<AnyValType, SetType, false, SET_LOOKUP>( \
135  context, val, num_args, args); \
136  } \
137 \
138  BooleanVal InPredicate::NotInSetLookup( \
139  FunctionContext* context, const AnyValType& val, int num_args, \
140  const AnyValType* args) { \
141  return TemplatedIn<AnyValType, SetType, true, SET_LOOKUP>( \
142  context, val, num_args, args); \
143  } \
144 \
145  BooleanVal InPredicate::InIterate( \
146  FunctionContext* context, const AnyValType& val, int num_args, \
147  const AnyValType* args) { \
148  return TemplatedIn<AnyValType, SetType, false, ITERATE>( \
149  context, val, num_args, args); \
150  } \
151 \
152  BooleanVal InPredicate::NotInIterate( \
153  FunctionContext* context, const AnyValType& val, int num_args, \
154  const AnyValType* args) { \
155  return TemplatedIn<AnyValType, SetType, true, ITERATE>( \
156  context, val, num_args, args); \
157  } \
158 \
159  void InPredicate::SetLookupPrepare_##type_name( \
160  FunctionContext* ctx, FunctionContext::FunctionStateScope scope) { \
161  SetLookupPrepare<AnyValType, SetType>(ctx, scope); \
162  } \
163 \
164  void InPredicate::SetLookupClose_##type_name( \
165  FunctionContext* ctx, FunctionContext::FunctionStateScope scope) { \
166  SetLookupClose<SetType>(ctx, scope); \
167  }
168 
169 IN_FUNCTIONS(BooleanVal, bool, boolean)
170 IN_FUNCTIONS(TinyIntVal, int8_t, tinyint)
171 IN_FUNCTIONS(SmallIntVal, int16_t, smallint)
172 IN_FUNCTIONS(IntVal, int32_t, int)
173 IN_FUNCTIONS(BigIntVal, int64_t, bigint)
174 IN_FUNCTIONS(FloatVal, float, float)
175 IN_FUNCTIONS(DoubleVal, double, double)
176 IN_FUNCTIONS(StringVal, StringValue, string)
177 IN_FUNCTIONS(TimestampVal, TimestampValue, timestamp)
179 
180 // Needed for in-predicate-benchmark to build
181 template BooleanVal InPredicate::Iterate<IntVal>(
182  const FunctionContext::TypeDesc*, const IntVal&, int, const IntVal*);
183 
184 }
int precision
Only valid if type == TYPE_DECIMAL.
Definition: udf.h:75
const FunctionContext::TypeDesc * type
The type of the arguments.
Definition: in-predicate.h:286
__int128_t val16
Definition: udf.h:572
DecimalValue< int128_t > Decimal16Value
Decimal16Value GetVal(const FunctionContext::TypeDesc *type, const DecimalVal &x)
This object has a compatible storage format with boost::ptime.
Definition: udf.h:495
bool is_null
Definition: udf.h:359
const TypeDesc * GetArgType(int arg_idx) const
Definition: udf.cc:425
void * GetFunctionState(FunctionStateScope scope) const
Definition: udf-ir.cc:38
bool contains_null
If true, there is at least one NULL constant in the IN list.
Definition: in-predicate.h:278
static BooleanVal null()
Definition: udf.h:368
bool IsArgConstant(int arg_idx) const
Definition: udf-ir.cc:20
void SetFunctionState(FunctionStateScope scope, void *ptr)
Definition: udf.cc:370
#define IN_FUNCTIONS(AnyValType, SetType, type_name)
int GetNumArgs() const
Definition: udf-ir.cc:30
AnyVal * GetConstantArg(int arg_idx) const
Definition: udf-ir.cc:25