Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
expr.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 <llvm/ExecutionEngine/ExecutionEngine.h>
18 #include <llvm/PassManager.h>
19 #include <llvm/Transforms/Scalar.h>
20 #include <llvm/Transforms/Utils/BasicBlockUtils.h>
21 #include <llvm/Transforms/Utils/UnrollLoop.h>
22 #include <llvm/Support/InstIterator.h>
23 #include <thrift/protocol/TDebugProtocol.h>
24 
25 #include "codegen/codegen-anyval.h"
26 #include "codegen/llvm-codegen.h"
27 #include "common/object-pool.h"
28 #include "common/status.h"
29 #include "exprs/anyval-util.h"
30 #include "exprs/expr.h"
31 #include "exprs/expr-context.h"
33 #include "exprs/case-expr.h"
34 #include "exprs/cast-functions.h"
39 #include "exprs/hive-udf-call.h"
40 #include "exprs/in-predicate.h"
42 #include "exprs/like-predicate.h"
43 #include "exprs/literal.h"
44 #include "exprs/math-functions.h"
45 #include "exprs/null-literal.h"
46 #include "exprs/operators.h"
47 #include "exprs/scalar-fn-call.h"
48 #include "exprs/slot-ref.h"
49 #include "exprs/string-functions.h"
52 #include "exprs/udf-builtins.h"
54 #include "gen-cpp/Exprs_types.h"
55 #include "gen-cpp/Data_types.h"
56 #include "runtime/lib-cache.h"
57 #include "runtime/runtime-state.h"
58 #include "runtime/raw-value.h"
59 #include "udf/udf.h"
60 #include "udf/udf-internal.h"
61 
62 #include "gen-cpp/Exprs_types.h"
63 #include "gen-cpp/ImpalaService_types.h"
64 
65 #include "common/names.h"
66 
67 using namespace impala;
68 using namespace impala_udf;
69 using namespace llvm;
70 
71 const char* Expr::LLVM_CLASS_NAME = "class.impala::Expr";
72 
73 template<class T>
74 bool ParseString(const string& str, T* val) {
75  istringstream stream(str);
76  stream >> *val;
77  return !stream.fail();
78 }
79 
81  int varargs_buffer_size) {
83  vector<FunctionContext::TypeDesc> arg_types;
84  for (int i = 0; i < children_.size(); ++i) {
85  arg_types.push_back(AnyValUtil::ColumnTypeToTypeDesc(children_[i]->type_));
86  }
87  context_index_ = ctx->Register(state, return_type, arg_types, varargs_buffer_size);
88  return ctx->fn_context(context_index_);
89 }
90 
91 Expr::Expr(const ColumnType& type, bool is_slotref)
92  : cache_entry_(NULL),
93  is_slotref_(is_slotref),
94  type_(type),
95  output_scale_(-1),
96  context_index_(-1),
97  ir_compute_fn_(NULL) {
98 }
99 
100 Expr::Expr(const TExprNode& node, bool is_slotref)
101  : cache_entry_(NULL),
102  is_slotref_(is_slotref),
103  type_(ColumnType(node.type)),
104  output_scale_(-1),
105  context_index_(-1),
106  ir_compute_fn_(NULL) {
107  if (node.__isset.fn) fn_ = node.fn;
108 }
109 
111  DCHECK(cache_entry_ == NULL);
112 }
113 
114 void Expr::Close(RuntimeState* state, ExprContext* context,
116  for (int i = 0; i < children_.size(); ++i) {
117  children_[i]->Close(state, context, scope);
118  }
119 
120  if (scope == FunctionContext::FRAGMENT_LOCAL) {
121  // This is the final, non-cloned context to close. Clean up the whole Expr.
122  if (cache_entry_ != NULL) {
124  cache_entry_ = NULL;
125  }
126  }
127 }
128 
129 Status Expr::CreateExprTree(ObjectPool* pool, const TExpr& texpr, ExprContext** ctx) {
130  // input is empty
131  if (texpr.nodes.size() == 0) {
132  *ctx = NULL;
133  return Status::OK;
134  }
135  int node_idx = 0;
136  Expr* e;
137  Status status = CreateTreeFromThrift(pool, texpr.nodes, NULL, &node_idx, &e, ctx);
138  if (status.ok() && node_idx + 1 != texpr.nodes.size()) {
139  status = Status(
140  "Expression tree only partially reconstructed. Not all thrift nodes were used.");
141  }
142  if (!status.ok()) {
143  LOG(ERROR) << "Could not construct expr tree.\n" << status.GetDetail() << "\n"
144  << apache::thrift::ThriftDebugString(texpr);
145  }
146  return status;
147 }
148 
149 Status Expr::CreateExprTrees(ObjectPool* pool, const vector<TExpr>& texprs,
150  vector<ExprContext*>* ctxs) {
151  ctxs->clear();
152  for (int i = 0; i < texprs.size(); ++i) {
153  ExprContext* ctx;
154  RETURN_IF_ERROR(CreateExprTree(pool, texprs[i], &ctx));
155  ctxs->push_back(ctx);
156  }
157  return Status::OK;
158 }
159 
160 Status Expr::CreateTreeFromThrift(ObjectPool* pool, const vector<TExprNode>& nodes,
161  Expr* parent, int* node_idx, Expr** root_expr, ExprContext** ctx) {
162  // propagate error case
163  if (*node_idx >= nodes.size()) {
164  return Status("Failed to reconstruct expression tree from thrift.");
165  }
166  int num_children = nodes[*node_idx].num_children;
167  Expr* expr = NULL;
168  RETURN_IF_ERROR(CreateExpr(pool, nodes[*node_idx], &expr));
169  DCHECK(expr != NULL);
170  if (parent != NULL) {
171  parent->AddChild(expr);
172  } else {
173  DCHECK(root_expr != NULL);
174  DCHECK(ctx != NULL);
175  *root_expr = expr;
176  *ctx = pool->Add(new ExprContext(expr));
177  }
178  for (int i = 0; i < num_children; i++) {
179  *node_idx += 1;
180  RETURN_IF_ERROR(CreateTreeFromThrift(pool, nodes, expr, node_idx, NULL, NULL));
181  // we are expecting a child, but have used all nodes
182  // this means we have been given a bad tree and must fail
183  if (*node_idx >= nodes.size()) {
184  return Status("Failed to reconstruct expression tree from thrift.");
185  }
186  }
187  return Status::OK;
188 }
189 
190 Status Expr::CreateExpr(ObjectPool* pool, const TExprNode& texpr_node, Expr** expr) {
191  switch (texpr_node.node_type) {
192  case TExprNodeType::BOOL_LITERAL:
193  case TExprNodeType::FLOAT_LITERAL:
194  case TExprNodeType::INT_LITERAL:
195  case TExprNodeType::STRING_LITERAL:
196  case TExprNodeType::DECIMAL_LITERAL:
197  *expr = pool->Add(new Literal(texpr_node));
198  return Status::OK;
199  case TExprNodeType::CASE_EXPR:
200  if (!texpr_node.__isset.case_expr) {
201  return Status("Case expression not set in thrift node");
202  }
203  *expr = pool->Add(new CaseExpr(texpr_node));
204  return Status::OK;
205  case TExprNodeType::COMPOUND_PRED:
206  if (texpr_node.fn.name.function_name == "and") {
207  *expr = pool->Add(new AndPredicate(texpr_node));
208  } else if (texpr_node.fn.name.function_name == "or") {
209  *expr = pool->Add(new OrPredicate(texpr_node));
210  } else {
211  DCHECK_EQ(texpr_node.fn.name.function_name, "not");
212  *expr = pool->Add(new ScalarFnCall(texpr_node));
213  }
214  return Status::OK;
215  case TExprNodeType::NULL_LITERAL:
216  *expr = pool->Add(new NullLiteral(texpr_node));
217  return Status::OK;
218  case TExprNodeType::SLOT_REF:
219  if (!texpr_node.__isset.slot_ref) {
220  return Status("Slot reference not set in thrift node");
221  }
222  *expr = pool->Add(new SlotRef(texpr_node));
223  return Status::OK;
224  case TExprNodeType::TUPLE_IS_NULL_PRED:
225  *expr = pool->Add(new TupleIsNullPredicate(texpr_node));
226  return Status::OK;
227  case TExprNodeType::FUNCTION_CALL:
228  if (!texpr_node.__isset.fn) {
229  return Status("Function not set in thrift node");
230  }
231  // Special-case functions that have their own Expr classes
232  // TODO: is there a better way to do this?
233  if (texpr_node.fn.name.function_name == "if") {
234  *expr = pool->Add(new IfExpr(texpr_node));
235  } else if (texpr_node.fn.name.function_name == "nullif") {
236  *expr = pool->Add(new NullIfExpr(texpr_node));
237  } else if (texpr_node.fn.name.function_name == "isnull" ||
238  texpr_node.fn.name.function_name == "ifnull" ||
239  texpr_node.fn.name.function_name == "nvl") {
240  *expr = pool->Add(new IsNullExpr(texpr_node));
241  } else if (texpr_node.fn.name.function_name == "coalesce") {
242  *expr = pool->Add(new CoalesceExpr(texpr_node));
243 
244  } else if (texpr_node.fn.binary_type == TFunctionBinaryType::HIVE) {
245  *expr = pool->Add(new HiveUdfCall(texpr_node));
246  } else {
247  *expr = pool->Add(new ScalarFnCall(texpr_node));
248  }
249  return Status::OK;
250  default:
251  stringstream os;
252  os << "Unknown expr node type: " << texpr_node.node_type;
253  return Status(os.str());
254  }
255 }
256 
258  int expr_idx;
261 
262  // TODO: sort by type as well? Any reason to do this?
263  bool operator<(const MemLayoutData& rhs) const {
264  // variable_len go at end
265  if (this->variable_length && !rhs.variable_length) return false;
266  if (!this->variable_length && rhs.variable_length) return true;
267  return this->byte_size < rhs.byte_size;
268  }
269 };
270 
271 int Expr::ComputeResultsLayout(const vector<Expr*>& exprs, vector<int>* offsets,
272  int* var_result_begin) {
273  if (exprs.size() == 0) {
274  *var_result_begin = -1;
275  return 0;
276  }
277 
278  vector<MemLayoutData> data;
279  data.resize(exprs.size());
280 
281  // Collect all the byte sizes and sort them
282  for (int i = 0; i < exprs.size(); ++i) {
283  data[i].expr_idx = i;
284  if (exprs[i]->type().IsVarLen()) {
285  data[i].byte_size = 16;
286  data[i].variable_length = true;
287  } else {
288  data[i].byte_size = exprs[i]->type().GetByteSize();
289  data[i].variable_length = false;
290  }
291  DCHECK_NE(data[i].byte_size, 0);
292  }
293 
294  sort(data.begin(), data.end());
295 
296  // Walk the types and store in a packed aligned layout
297  int max_alignment = sizeof(int64_t);
298  int current_alignment = data[0].byte_size;
299  int byte_offset = 0;
300 
301  offsets->resize(exprs.size());
302  offsets->clear();
303  *var_result_begin = -1;
304 
305  for (int i = 0; i < data.size(); ++i) {
306  DCHECK_GE(data[i].byte_size, current_alignment);
307  // Don't align more than word (8-byte) size. This is consistent with what compilers
308  // do.
309  if (exprs[data[i].expr_idx]->type().type == TYPE_CHAR &&
310  !exprs[data[i].expr_idx]->type().IsVarLen()) {
311  // CHARs are not padded, to be consistent with complier layouts
312  // aligns the next value on an 8 byte boundary
313  current_alignment = (data[i].byte_size + current_alignment) % max_alignment;
314  } else if (data[i].byte_size != current_alignment &&
315  current_alignment != max_alignment) {
316  byte_offset += data[i].byte_size - current_alignment;
317  current_alignment = min(data[i].byte_size, max_alignment);
318  }
319  (*offsets)[data[i].expr_idx] = byte_offset;
320  if (data[i].variable_length && *var_result_begin == -1) {
321  *var_result_begin = byte_offset;
322  }
323  byte_offset += data[i].byte_size;
324  }
325 
326  return byte_offset;
327 }
328 
329 int Expr::ComputeResultsLayout(const vector<ExprContext*>& ctxs, vector<int>* offsets,
330  int* var_result_begin) {
331  vector<Expr*> exprs;
332  for (int i = 0; i < ctxs.size(); ++i) exprs.push_back(ctxs[i]->root());
333  return ComputeResultsLayout(exprs, offsets, var_result_begin);
334 }
335 
336 void Expr::Close(const vector<ExprContext*>& ctxs, RuntimeState* state) {
337  for (int i = 0; i < ctxs.size(); ++i) {
338  ctxs[i]->Close(state);
339  }
340 }
341 
342 Status Expr::Prepare(const vector<ExprContext*>& ctxs, RuntimeState* state,
344  for (int i = 0; i < ctxs.size(); ++i) {
345  RETURN_IF_ERROR(ctxs[i]->Prepare(state, row_desc, tracker));
346  }
347  return Status::OK;
348 }
349 
351  ExprContext* context) {
352  DCHECK(type_.type != INVALID_TYPE);
353  for (int i = 0; i < children_.size(); ++i) {
354  RETURN_IF_ERROR(children_[i]->Prepare(state, row_desc, context));
355  }
356  return Status::OK;
357 }
358 
359 Status Expr::Open(const vector<ExprContext*>& ctxs, RuntimeState* state) {
360  for (int i = 0; i < ctxs.size(); ++i) {
361  RETURN_IF_ERROR(ctxs[i]->Open(state));
362  }
363  return Status::OK;
364 }
365 
368  for (int i = 0; i < children_.size(); ++i) {
369  RETURN_IF_ERROR(children_[i]->Open(state, context, scope));
370  }
371  return Status::OK;
372 }
373 
374 Status Expr::Clone(const vector<ExprContext*>& ctxs, RuntimeState* state,
375  vector<ExprContext*>* new_ctxs) {
376  DCHECK(new_ctxs != NULL);
377  DCHECK(new_ctxs->empty());
378  new_ctxs->resize(ctxs.size());
379  for (int i = 0; i < ctxs.size(); ++i) {
380  RETURN_IF_ERROR(ctxs[i]->Clone(state, &(*new_ctxs)[i]));
381  }
382  return Status::OK;
383 }
384 
385 string Expr::DebugString() const {
386  // TODO: implement partial debug string for member vars
387  stringstream out;
388  out << " type=" << type_.DebugString();
389  if (!children_.empty()) {
390  out << " children=" << DebugString(children_);
391  }
392  return out.str();
393 }
394 
395 string Expr::DebugString(const vector<Expr*>& exprs) {
396  stringstream out;
397  out << "[";
398  for (int i = 0; i < exprs.size(); ++i) {
399  out << (i == 0 ? "" : " ") << exprs[i]->DebugString();
400  }
401  out << "]";
402  return out.str();
403 }
404 
405 string Expr::DebugString(const vector<ExprContext*>& ctxs) {
406  vector<Expr*> exprs;
407  for (int i = 0; i < ctxs.size(); ++i) exprs.push_back(ctxs[i]->root());
408  return DebugString(exprs);
409 }
410 
411 bool Expr::IsConstant() const {
412  for (int i = 0; i < children_.size(); ++i) {
413  if (!children_[i]->IsConstant()) return false;
414  }
415  return true;
416 }
417 
418 int Expr::GetSlotIds(vector<SlotId>* slot_ids) const {
419  int n = 0;
420  for (int i = 0; i < children_.size(); ++i) {
421  n += children_[i]->GetSlotIds(slot_ids);
422  }
423  return n;
424 }
425 
427  switch (type.type) {
428  case TYPE_BOOLEAN:
429  return codegen->GetFunction(IRFunction::EXPR_GET_BOOLEAN_VAL);
430  case TYPE_TINYINT:
431  return codegen->GetFunction(IRFunction::EXPR_GET_TINYINT_VAL);
432  case TYPE_SMALLINT:
433  return codegen->GetFunction(IRFunction::EXPR_GET_SMALLINT_VAL);
434  case TYPE_INT:
435  return codegen->GetFunction(IRFunction::EXPR_GET_INT_VAL);
436  case TYPE_BIGINT:
437  return codegen->GetFunction(IRFunction::EXPR_GET_BIGINT_VAL);
438  case TYPE_FLOAT:
439  return codegen->GetFunction(IRFunction::EXPR_GET_FLOAT_VAL);
440  case TYPE_DOUBLE:
441  return codegen->GetFunction(IRFunction::EXPR_GET_DOUBLE_VAL);
442  case TYPE_STRING:
443  case TYPE_CHAR:
444  case TYPE_VARCHAR:
445  return codegen->GetFunction(IRFunction::EXPR_GET_STRING_VAL);
446  case TYPE_TIMESTAMP:
447  return codegen->GetFunction(IRFunction::EXPR_GET_TIMESTAMP_VAL);
448  case TYPE_DECIMAL:
449  return codegen->GetFunction(IRFunction::EXPR_GET_DECIMAL_VAL);
450  default:
451  DCHECK(false) << "Invalid type: " << type.DebugString();
452  return NULL;
453  }
454 }
455 
456 Function* Expr::CreateIrFunctionPrototype(LlvmCodeGen* codegen, const string& name,
457  Value* (*args)[2]) {
458  Type* return_type = CodegenAnyVal::GetLoweredType(codegen, type());
459  LlvmCodeGen::FnPrototype prototype(codegen, name, return_type);
460  prototype.AddArgument(
462  "context", codegen->GetPtrType(ExprContext::LLVM_CLASS_NAME)));
463  prototype.AddArgument(
465  Function* function = prototype.GeneratePrototype(NULL, args[0]);
466  DCHECK(function != NULL);
467  return function;
468 }
469 
471  // Call one function from each of the classes to pull all the symbols
472  // from that class in.
473  // TODO: is there a better way to do this?
474  AggregateFunctions::InitNull(NULL, NULL);
475  CastFunctions::CastToBooleanVal(NULL, TinyIntVal::null());
476  CompoundPredicate::Not(NULL, BooleanVal::null());
477  ConditionalFunctions::NullIfZero(NULL, TinyIntVal::null());
478  DecimalFunctions::Precision(NULL, DecimalVal::null());
479  DecimalOperators::CastToDecimalVal(NULL, DecimalVal::null());
480  InPredicate::InIterate(NULL, BigIntVal::null(), 0, NULL);
481  IsNullPredicate::IsNull(NULL, BooleanVal::null());
482  LikePredicate::Like(NULL, StringVal::null(), StringVal::null());
483  Operators::Add_IntVal_IntVal(NULL, IntVal::null(), IntVal::null());
484  MathFunctions::Pi(NULL);
485  StringFunctions::Length(NULL, StringVal::null());
486  TimestampFunctions::Year(NULL, TimestampVal::null());
487  UdfBuiltins::Pi(NULL);
488  UtilityFunctions::Pid(NULL);
489 }
490 
492  DCHECK(context->opened_);
493  if (!IsConstant()) return NULL;
494  if (constant_val_.get() != NULL) return constant_val_.get();
495 
496  switch (type_.type) {
497  case TYPE_BOOLEAN: {
498  constant_val_.reset(new BooleanVal(GetBooleanVal(context, NULL)));
499  break;
500  }
501  case TYPE_TINYINT: {
502  constant_val_.reset(new TinyIntVal(GetTinyIntVal(context, NULL)));
503  break;
504  }
505  case TYPE_SMALLINT: {
506  constant_val_.reset(new SmallIntVal(GetSmallIntVal(context, NULL)));
507  break;
508  }
509  case TYPE_INT: {
510  constant_val_.reset(new IntVal(GetIntVal(context, NULL)));
511  break;
512  }
513  case TYPE_BIGINT: {
514  constant_val_.reset(new BigIntVal(GetBigIntVal(context, NULL)));
515  break;
516  }
517  case TYPE_FLOAT: {
518  constant_val_.reset(new FloatVal(GetFloatVal(context, NULL)));
519  break;
520  }
521  case TYPE_DOUBLE: {
522  constant_val_.reset(new DoubleVal(GetDoubleVal(context, NULL)));
523  break;
524  }
525  case TYPE_STRING:
526  case TYPE_CHAR:
527  case TYPE_VARCHAR: {
528  constant_val_.reset(new StringVal(GetStringVal(context, NULL)));
529  break;
530  }
531  case TYPE_TIMESTAMP: {
532  constant_val_.reset(new TimestampVal(GetTimestampVal(context, NULL)));
533  break;
534  }
535  case TYPE_DECIMAL: {
536  constant_val_.reset(new DecimalVal(GetDecimalVal(context, NULL)));
537  break;
538  }
539  default:
540  DCHECK(false) << "Type not implemented: " << type();
541  }
542  DCHECK(constant_val_.get() != NULL);
543  return constant_val_.get();
544 }
545 
547  if (ir_compute_fn_ != NULL) {
548  *fn = ir_compute_fn_;
549  return Status::OK;
550  }
551  LlvmCodeGen* codegen;
552  RETURN_IF_ERROR(state->GetCodegen(&codegen));
553  Function* static_getval_fn = GetStaticGetValWrapper(type(), codegen);
554 
555  // Call it passing this as the additional first argument.
556  Value* args[2];
557  ir_compute_fn_ = CreateIrFunctionPrototype(codegen, "CodegenComputeFnWrapper", &args);
558  BasicBlock* entry_block =
559  BasicBlock::Create(codegen->context(), "entry", ir_compute_fn_);
560  LlvmCodeGen::LlvmBuilder builder(entry_block);
561  Value* this_ptr =
562  codegen->CastPtrToLlvmPtr(codegen->GetPtrType(Expr::LLVM_CLASS_NAME), this);
563  Value* compute_fn_args[] = { this_ptr, args[0], args[1] };
564  Value* ret = CodegenAnyVal::CreateCall(
565  codegen, &builder, static_getval_fn, compute_fn_args, "ret");
566  builder.CreateRet(ret);
568  *fn = ir_compute_fn_;
569  return Status::OK;
570 }
571 
572 // At least one of these should always be subclassed.
574  DCHECK(false) << DebugString();
575  return BooleanVal::null();
576 }
578  DCHECK(false) << DebugString();
579  return TinyIntVal::null();
580 }
582  DCHECK(false) << DebugString();
583  return SmallIntVal::null();
584 }
586  DCHECK(false) << DebugString();
587  return IntVal::null();
588 }
590  DCHECK(false) << DebugString();
591  return BigIntVal::null();
592 }
594  DCHECK(false) << DebugString();
595  return FloatVal::null();
596 }
598  DCHECK(false) << DebugString();
599  return DoubleVal::null();
600 }
602  DCHECK(false) << DebugString();
603  return StringVal::null();
604 }
606  DCHECK(false) << DebugString();
607  return TimestampVal::null();
608 }
610  DCHECK(false) << DebugString();
611  return DecimalVal::null();
612 }
static IntVal Year(FunctionContext *context, const TimestampVal &ts_val)
Functions to extract parts of the timestamp, return integers.
If the UDF ran into an error, the FE throws an exception.
Definition: hive-udf-call.h:57
bool IsVarLen() const
Definition: types.h:172
llvm::Function * ir_compute_fn_
Cached codegened compute function. Exprs should set this in GetCodegendComputeFn().
Definition: expr.h:299
int expr_idx
Definition: expr.cc:258
static FunctionContext::TypeDesc ColumnTypeToTypeDesc(const ColumnType &type)
Definition: anyval-util.cc:52
static Status CreateTreeFromThrift(ObjectPool *pool, const std::vector< TExprNode > &nodes, Expr *parent, int *node_idx, Expr **root_expr, ExprContext **ctx)
Definition: expr.cc:160
const std::string GetDetail() const
Definition: status.cc:184
static TinyIntVal NullIfZero(FunctionContext *context, const TinyIntVal &val)
static impala_udf::BooleanVal InIterate(impala_udf::FunctionContext *context, const impala_udf::BooleanVal &val, int num_args, const impala_udf::BooleanVal *args)
Functions for every type.
virtual IntVal GetIntVal(ExprContext *context, TupleRow *)
Definition: expr.cc:585
llvm::PointerType * GetPtrType(llvm::Type *type)
Return a pointer type to 'type'.
virtual TimestampVal GetTimestampVal(ExprContext *context, TupleRow *)
Definition: expr.cc:605
static void InitNull(FunctionContext *, AnyVal *dst)
Initializes dst to NULL.
virtual int GetSlotIds(std::vector< SlotId > *slot_ids) const
Definition: expr.cc:418
friend class CaseExpr
Definition: expr.h:246
MemTracker tracker
virtual SmallIntVal GetSmallIntVal(ExprContext *context, TupleRow *)
Definition: expr.cc:581
static Status Clone(const std::vector< ExprContext * > &ctxs, RuntimeState *state, std::vector< ExprContext * > *new_ctxs)
Definition: expr.cc:374
Expr(const ColumnType &type, bool is_slotref=false)
Definition: expr.cc:91
Utility struct that wraps a variable name and llvm type.
Definition: llvm-codegen.h:149
static Status Open(const std::vector< ExprContext * > &ctxs, RuntimeState *state)
Convenience function for opening multiple expr trees.
static BooleanVal CastToBooleanVal(FunctionContext *context, const TinyIntVal &val)
friend class ScalarFnCall
Definition: expr.h:249
#define RETURN_IF_ERROR(stmt)
some generally useful macros
Definition: status.h:242
static llvm::Value * CreateCall(LlvmCodeGen *cg, LlvmCodeGen::LlvmBuilder *builder, llvm::Function *fn, llvm::ArrayRef< llvm::Value * > args, const char *name="", llvm::Value *result_ptr=NULL)
'name' optionally specifies the name of the returned value.
virtual BooleanVal GetBooleanVal(ExprContext *context, TupleRow *)
Definition: expr.cc:573
virtual DoubleVal GetDoubleVal(ExprContext *context, TupleRow *)
Definition: expr.cc:597
static IntVal Precision(FunctionContext *context, const DecimalVal &val)
static impala_udf::BooleanVal Like(impala_udf::FunctionContext *context, const impala_udf::StringVal &val, const impala_udf::StringVal &pattern)
virtual bool IsConstant() const
Definition: expr.cc:411
This object has a compatible storage format with boost::ptime.
Definition: udf.h:495
virtual StringVal GetStringVal(ExprContext *context, TupleRow *)
Definition: expr.cc:601
virtual DecimalVal GetDecimalVal(ExprContext *context, TupleRow *)
Definition: expr.cc:609
static void Close(const std::vector< ExprContext * > &ctxs, RuntimeState *state)
Convenience function for closing multiple expr trees.
Expr for evaluating and (&&) operators.
boost::scoped_ptr< AnyVal > constant_val_
Definition: expr.h:303
static DoubleVal Pi(FunctionContext *)
LLVM code generator. This is the top level object to generate jitted code.
Definition: llvm-codegen.h:107
llvm::Function * CreateIrFunctionPrototype(LlvmCodeGen *codegen, const std::string &name, llvm::Value *(*args)[2])
Definition: expr.cc:456
std::string DebugString() const
Definition: types.cc:194
void AddChild(Expr *expr)
Definition: expr.h:141
static const char * LLVM_CLASS_NAME
Definition: tuple-row.h:76
friend class ExprContext
Definition: expr.h:339
llvm::Function * GeneratePrototype(LlvmBuilder *builder=NULL, llvm::Value **params=NULL)
static const char * LLVM_CLASS_NAME
Definition: expr-context.h:126
PrimitiveType type
Definition: types.h:60
llvm::Value * CastPtrToLlvmPtr(llvm::Type *type, const void *ptr)
void AddArgument(const NamedVariable &var)
Add argument.
Definition: llvm-codegen.h:171
static const char * LLVM_CLASS_NAME
Definition: expr.h:232
virtual AnyVal * GetConstVal(ExprContext *context)
Definition: expr.cc:491
Status GetCodegendComputeFnWrapper(RuntimeState *state, llvm::Function **fn)
Definition: expr.cc:546
static DoubleVal Pi(FunctionContext *context)
Definition: udf-builtins.cc:42
ObjectPool pool
static llvm::Type * GetLoweredType(LlvmCodeGen *cg, const ColumnType &type)
llvm::Function * GetFunction(IRFunction::Type)
LibCache::LibCacheEntry * cache_entry_
Cache entry for the library implementing this function.
Definition: expr.h:281
This is the superclass of all expr evaluation nodes.
Definition: expr.h:116
virtual FloatVal GetFloatVal(ExprContext *context, TupleRow *)
Definition: expr.cc:593
static LibCache * instance()
Definition: lib-cache.h:63
static int ComputeResultsLayout(const std::vector< Expr * > &exprs, std::vector< int > *offsets, int *var_result_begin)
This class is thread-safe.
Definition: mem-tracker.h:61
const RowDescriptor & row_desc() const
static DecimalVal CastToDecimalVal(FunctionContext *, const DecimalVal &)
virtual BigIntVal GetBigIntVal(ExprContext *context, TupleRow *)
Definition: expr.cc:589
virtual ~Expr()
Definition: expr.cc:110
static IntVal Length(FunctionContext *, const StringVal &str)
static Status CreateExprTree(ObjectPool *pool, const TExpr &texpr, ExprContext **ctx)
Definition: expr.cc:129
TFunction fn_
Function description.
Definition: expr.h:284
bool variable_length
Definition: expr.cc:260
const ColumnType & type() const
Definition: expr.h:145
Expr for evaluating or (||) operators.
Reference to a single slot of a tuple.
Definition: slot-ref.h:23
static void InitBuiltinsDummy()
Definition: expr.cc:470
static const Status OK
Definition: status.h:87
Status GetCodegen(LlvmCodeGen **codegen, bool initialize=true)
virtual TinyIntVal GetTinyIntVal(ExprContext *context, TupleRow *)
Definition: expr.cc:577
static Status CreateExpr(ObjectPool *pool, const TExprNode &texpr_node, Expr **expr)
Create a new Expr based on texpr_node.node_type within 'pool'.
Definition: expr.cc:190
int Register(RuntimeState *state, const FunctionContext::TypeDesc &return_type, const std::vector< FunctionContext::TypeDesc > &arg_types, int varargs_buffer_size=0)
Definition: expr-context.cc:81
const ColumnType type_
analysis is done, types are fixed at this point
Definition: expr.h:289
bool operator<(const MemLayoutData &rhs) const
Definition: expr.cc:263
FunctionContext * fn_context(int i)
Definition: expr-context.h:100
bool ParseString(const string &str, T *val)
Definition: literal.cc:184
static Status CreateExprTrees(ObjectPool *pool, const std::vector< TExpr > &texprs, std::vector< ExprContext * > *ctxs)
Definition: expr.cc:149
llvm::Function * FinalizeFunction(llvm::Function *function)
static Status Prepare(const std::vector< ExprContext * > &ctxs, RuntimeState *state, const RowDescriptor &row_desc, MemTracker *tracker)
void DecrementUseCount(LibCacheEntry *entry)
See comment in GetSoFunctionPtr().
Definition: lib-cache.cc:170
int byte_size
Definition: expr.cc:259
bool ok() const
Definition: status.h:172
std::vector< Expr * > children_
Definition: expr.h:290
static BooleanVal IsNull(FunctionContext *ctx, const T &val)
llvm::Function * GetStaticGetValWrapper(ColumnType type, LlvmCodeGen *codegen)
Definition: expr.cc:426
string name
Definition: cpu-info.cc:50
llvm::LLVMContext & context()
Definition: llvm-codegen.h:214
virtual std::string DebugString() const
Definition: expr.cc:385
static BooleanVal Not(FunctionContext *context, const BooleanVal &)
FunctionContext * RegisterFunctionContext(ExprContext *ctx, RuntimeState *state, int varargs_buffer_size=0)
Definition: expr.cc:80
static IntVal Pid(FunctionContext *ctx)
static IntVal Add_IntVal_IntVal(FunctionContext *, const IntVal &, const IntVal &)