Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
slot-ref.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 "exprs/slot-ref.h"
16 
17 #include <sstream>
18 
19 #include "codegen/codegen-anyval.h"
20 #include "codegen/llvm-codegen.h"
21 #include "gen-cpp/Exprs_types.h"
22 #include "runtime/runtime-state.h"
23 
24 #include "common/names.h"
25 
26 using namespace impala_udf;
27 using namespace llvm;
28 
29 namespace impala {
30 
31 SlotRef::SlotRef(const TExprNode& node)
32  : Expr(node, true),
33  slot_offset_(-1), // invalid
34  null_indicator_offset_(0, 0),
35  slot_id_(node.slot_ref.slot_id) {
36  // slot_/null_indicator_offset_ are set in Prepare()
37 }
38 
40  : Expr(desc->type(), true),
41  slot_offset_(-1),
42  null_indicator_offset_(0, 0),
43  slot_id_(desc->id()) {
44  // slot_/null_indicator_offset_ are set in Prepare()
45 }
46 
47 SlotRef::SlotRef(const SlotDescriptor* desc, const ColumnType& type)
48  : Expr(type, true),
49  slot_offset_(-1),
50  null_indicator_offset_(0, 0),
51  slot_id_(desc->id()) {
52  // slot_/null_indicator_offset_ are set in Prepare()
53 }
54 
56  : Expr(type, true),
57  tuple_idx_(0),
58  slot_offset_(offset),
59  null_indicator_offset_(0, -1),
60  slot_id_(-1) {
61 }
62 
64  ExprContext* context) {
65  DCHECK_EQ(children_.size(), 0);
66  if (slot_id_ == -1) return Status::OK;
67 
68  const SlotDescriptor* slot_desc = state->desc_tbl().GetSlotDescriptor(slot_id_);
69  if (slot_desc == NULL) {
70  // TODO: create macro MAKE_ERROR() that returns a stream
71  stringstream error;
72  error << "couldn't resolve slot descriptor " << slot_id_;
73  LOG(INFO) << error.str();
74  return Status(error.str());
75  }
76  if (!slot_desc->is_materialized()) {
77  stringstream error;
78  error << "reference to non-materialized slot " << slot_id_;
79  return Status(error.str());
80  }
81  // TODO(marcel): get from runtime state
82  tuple_idx_ = row_desc.GetTupleIdx(slot_desc->parent());
84  TupleDescriptor* d = state->desc_tbl().GetTupleDescriptor(slot_desc->parent());
85  LOG(INFO) << "invalid idx: " << slot_desc->DebugString()
86  << "\nparent=" << d->DebugString()
87  << "\nrow=" << row_desc.DebugString();
88  stringstream error;
89  error << "invalid tuple_idx";
90  return Status(error.str());
91  }
94  slot_offset_ = slot_desc->tuple_offset();
96  return Status::OK;
97 }
98 
99 int SlotRef::GetSlotIds(vector<SlotId>* slot_ids) const {
100  slot_ids->push_back(slot_id_);
101  return 1;
102 }
103 
104 string SlotRef::DebugString() const {
105  stringstream out;
106  out << "SlotRef(slot_id=" << slot_id_
107  << " tuple_idx=" << tuple_idx_ << " slot_offset=" << slot_offset_
108  << " tuple_is_nullable=" << tuple_is_nullable_
109  << " null_indicator=" << null_indicator_offset_
110  << Expr::DebugString() << ")";
111  return out.str();
112 }
113 
114 // There are four possible cases we may generate:
115 // 1. Tuple is non-nullable and slot is non-nullable
116 // 2. Tuple is non-nullable and slot is nullable
117 // 3. Tuple is nullable and slot is non-nullable (when the aggregate output is the
118 // "nullable" side of an outer join).
119 // 4. Tuple is nullable and slot is nullable
120 //
121 // Resulting IR for a bigint slotref:
122 // (Note: some of the GEPs that look like no-ops are because certain offsets are 0
123 // in this slot descriptor.)
124 //
125 // define { i8, i64 } @GetSlotRef(i8** %context, %"class.impala::TupleRow"* %row) {
126 // entry:
127 // %cast_row_ptr = bitcast %"class.impala::TupleRow"* %row to i8**
128 // %tuple_addr = getelementptr i8** %cast_row_ptr, i32 0
129 // %tuple_ptr = load i8** %tuple_addr
130 // br label %check_slot_null
131 //
132 // check_slot_null: ; preds = %entry
133 // %null_ptr = getelementptr i8* %tuple_ptr, i32 0
134 // %null_byte = load i8* %null_ptr
135 // %null_byte_set = and i8 %null_byte, 2
136 // %slot_is_null = icmp ne i8 %null_byte_set, 0
137 // br i1 %slot_is_null, label %ret, label %get_slot
138 //
139 // get_slot: ; preds = %check_slot_null
140 // %slot_addr = getelementptr i8* %tuple_ptr, i32 8
141 // %val_ptr = bitcast i8* %slot_addr to i64*
142 // %val = load i64* %val_ptr
143 // br label %ret
144 //
145 // ret: ; preds = %get_slot, %check_slot_null
146 // %is_null_phi = phi i8 [ 1, %check_slot_null ], [ 0, %get_slot ]
147 // %val_phi = phi i64 [ 0, %check_slot_null ], [ %val, %get_slot ]
148 // %result = insertvalue { i8, i64 } zeroinitializer, i8 %is_null_phi, 0
149 // %result1 = insertvalue { i8, i64 } %result, i64 %val_phi, 1
150 // ret { i8, i64 } %result1
151 // }
152 //
153 // TODO: We could generate a typed struct (and not a char*) for Tuple for llvm. We know
154 // the types from the TupleDesc. It will likey make this code simpler to reason about.
155 Status SlotRef::GetCodegendComputeFn(RuntimeState* state, llvm::Function** fn) {
156  if (type_.type == TYPE_CHAR) {
157  *fn = NULL;
158  return Status("Codegen for Char not supported.");
159  }
160  if (ir_compute_fn_ != NULL) {
161  *fn = ir_compute_fn_;
162  return Status::OK;
163  }
164 
165  DCHECK_EQ(GetNumChildren(), 0);
166  LlvmCodeGen* codegen;
167  RETURN_IF_ERROR(state->GetCodegen(&codegen));
168 
169  // SlotRefs are based on the slot_id and tuple_idx. Combine them to make a
170  // query-wide unique id. We also need to combine whether the tuple is nullable. For
171  // example, in an outer join the scan node could have the same tuple id and slot id
172  // as the join node. When the slot is being used in the scan-node, the tuple is
173  // non-nullable. Used in the join node (and above in the plan tree), it is nullable.
174  // TODO: can we do something better.
175  const int64_t TUPLE_NULLABLE_MASK = 1L << 63;
176  int64_t unique_slot_id = slot_id_ | ((int64_t)tuple_idx_) << 32;
177  DCHECK_EQ(unique_slot_id & TUPLE_NULLABLE_MASK, 0);
178  if (tuple_is_nullable_) unique_slot_id |= TUPLE_NULLABLE_MASK;
179  Function* ir_compute_fn_ = codegen->GetRegisteredExprFn(unique_slot_id);
180  if (ir_compute_fn_ != NULL) {
181  *fn = ir_compute_fn_;
182  return Status::OK;
183  }
184 
185  LLVMContext& context = codegen->context();
186  Value* args[2];
187  *fn = CreateIrFunctionPrototype(codegen, "GetSlotRef", &args);
188  Value* row_ptr = args[1];
189 
190  Value* tuple_offset = ConstantInt::get(codegen->int_type(), tuple_idx_);
191  Value* null_byte_offset =
192  ConstantInt::get(codegen->int_type(), null_indicator_offset_.byte_offset);
193  Value* slot_offset = ConstantInt::get(codegen->int_type(), slot_offset_);
194  Value* null_mask =
195  ConstantInt::get(codegen->tinyint_type(), null_indicator_offset_.bit_mask);
196  Value* zero = ConstantInt::get(codegen->GetType(TYPE_TINYINT), 0);
197  Value* one = ConstantInt::get(codegen->GetType(TYPE_TINYINT), 1);
198 
199  BasicBlock* entry_block = BasicBlock::Create(context, "entry", *fn);
200  BasicBlock* check_slot_null_indicator_block = NULL;
201  if (null_indicator_offset_.bit_mask != 0) {
202  check_slot_null_indicator_block =
203  BasicBlock::Create(context, "check_slot_null", *fn);
204  }
205  BasicBlock* get_slot_block = BasicBlock::Create(context, "get_slot", *fn);
206  BasicBlock* ret_block = BasicBlock::Create(context, "ret", *fn);
207 
208  LlvmCodeGen::LlvmBuilder builder(entry_block);
209  // Get the tuple offset addr from the row
210  Value* cast_row_ptr = builder.CreateBitCast(
211  row_ptr, PointerType::get(codegen->ptr_type(), 0), "cast_row_ptr");
212  Value* tuple_addr = builder.CreateGEP(cast_row_ptr, tuple_offset, "tuple_addr");
213  // Load the tuple*
214  Value* tuple_ptr = builder.CreateLoad(tuple_addr, "tuple_ptr");
215 
216  // Check if tuple* is null only if the tuple is nullable
217  if (tuple_is_nullable_) {
218  Value* tuple_is_null = builder.CreateIsNull(tuple_ptr, "tuple_is_null");
219  // Check slot is null only if the null indicator bit is set
220  if (null_indicator_offset_.bit_mask == 0) {
221  builder.CreateCondBr(tuple_is_null, ret_block, get_slot_block);
222  } else {
223  builder.CreateCondBr(tuple_is_null, ret_block, check_slot_null_indicator_block);
224  }
225  } else {
226  if (null_indicator_offset_.bit_mask == 0) {
227  builder.CreateBr(get_slot_block);
228  } else {
229  builder.CreateBr(check_slot_null_indicator_block);
230  }
231  }
232 
233  // Branch for tuple* != NULL. Need to check if null-indicator is set
234  if (check_slot_null_indicator_block != NULL) {
235  builder.SetInsertPoint(check_slot_null_indicator_block);
236  Value* null_addr = builder.CreateGEP(tuple_ptr, null_byte_offset, "null_ptr");
237  Value* null_val = builder.CreateLoad(null_addr, "null_byte");
238  Value* slot_null_mask = builder.CreateAnd(null_val, null_mask, "null_byte_set");
239  Value* is_slot_null = builder.CreateICmpNE(slot_null_mask, zero, "slot_is_null");
240  builder.CreateCondBr(is_slot_null, ret_block, get_slot_block);
241  }
242 
243  // Branch for slot != NULL
244  builder.SetInsertPoint(get_slot_block);
245  Value* slot_ptr = builder.CreateGEP(tuple_ptr, slot_offset, "slot_addr");
246  Value* val_ptr = builder.CreateBitCast(slot_ptr, codegen->GetPtrType(type_), "val_ptr");
247  // Depending on the type, load the values we need
248  Value* val = NULL;
249  Value* ptr = NULL;
250  Value* len = NULL;
251  Value* time_of_day = NULL;
252  Value* date = NULL;
253  if (type_.IsStringType()) {
254  Value* ptr_ptr = builder.CreateStructGEP(val_ptr, 0, "ptr_ptr");
255  ptr = builder.CreateLoad(ptr_ptr, "ptr");
256  Value* len_ptr = builder.CreateStructGEP(val_ptr, 1, "len_ptr");
257  len = builder.CreateLoad(len_ptr, "len");
258  } else if (type() == TYPE_TIMESTAMP) {
259  Value* time_of_day_ptr = builder.CreateStructGEP(val_ptr, 0, "time_of_day_ptr");
260  // Cast boost::posix_time::time_duration to i64
261  Value* time_of_day_cast =
262  builder.CreateBitCast(time_of_day_ptr, codegen->GetPtrType(TYPE_BIGINT));
263  time_of_day = builder.CreateLoad(time_of_day_cast, "time_of_day");
264  Value* date_ptr = builder.CreateStructGEP(val_ptr, 1, "date_ptr");
265  // Cast boost::gregorian::date to i32
266  Value* date_cast = builder.CreateBitCast(date_ptr, codegen->GetPtrType(TYPE_INT));
267  date = builder.CreateLoad(date_cast, "date");
268  } else {
269  // val_ptr is a native type
270  val = builder.CreateLoad(val_ptr, "val");
271  }
272  builder.CreateBr(ret_block);
273 
274  // Return block
275  builder.SetInsertPoint(ret_block);
276  PHINode* is_null_phi = builder.CreatePHI(codegen->tinyint_type(), 2, "is_null_phi");
277  if (tuple_is_nullable_) is_null_phi->addIncoming(one, entry_block);
278  if (check_slot_null_indicator_block != NULL) {
279  is_null_phi->addIncoming(one, check_slot_null_indicator_block);
280  }
281  is_null_phi->addIncoming(zero, get_slot_block);
282 
283  // Depending on the type, create phi nodes for each value needed to populate the return
284  // *Val. The optimizer does a better job when there is a phi node for each value, rather
285  // than having get_slot_block generate an AnyVal and having a single phi node over that.
286  // TODO: revisit this code, can possibly be simplified
287  if (type().IsVarLen()) {
288  DCHECK(ptr != NULL);
289  DCHECK(len != NULL);
290  PHINode* ptr_phi = builder.CreatePHI(ptr->getType(), 2, "ptr_phi");
291  Value* null = Constant::getNullValue(ptr->getType());
292  if (tuple_is_nullable_) {
293  ptr_phi->addIncoming(null, entry_block);
294  }
295  if (check_slot_null_indicator_block != NULL) {
296  ptr_phi->addIncoming(null, check_slot_null_indicator_block);
297  }
298  ptr_phi->addIncoming(ptr, get_slot_block);
299 
300  PHINode* len_phi = builder.CreatePHI(len->getType(), 2, "len_phi");
301  null = ConstantInt::get(len->getType(), 0);
302  if (tuple_is_nullable_) {
303  len_phi->addIncoming(null, entry_block);
304  }
305  if (check_slot_null_indicator_block != NULL) {
306  len_phi->addIncoming(null, check_slot_null_indicator_block);
307  }
308  len_phi->addIncoming(len, get_slot_block);
309 
310  CodegenAnyVal result =
311  CodegenAnyVal::GetNonNullVal(codegen, &builder, type(), "result");
312  result.SetIsNull(is_null_phi);
313  result.SetPtr(ptr_phi);
314  result.SetLen(len_phi);
315  builder.CreateRet(result.value());
316  } else if (type() == TYPE_TIMESTAMP) {
317  DCHECK(time_of_day != NULL);
318  DCHECK(date != NULL);
319  PHINode* time_of_day_phi =
320  builder.CreatePHI(time_of_day->getType(), 2, "time_of_day_phi");
321  Value* null = ConstantInt::get(time_of_day->getType(), 0);
322  if (tuple_is_nullable_) {
323  time_of_day_phi->addIncoming(null, entry_block);
324  }
325  if (check_slot_null_indicator_block != NULL) {
326  time_of_day_phi->addIncoming(null, check_slot_null_indicator_block);
327  }
328  time_of_day_phi->addIncoming(time_of_day, get_slot_block);
329 
330  PHINode* date_phi = builder.CreatePHI(date->getType(), 2, "date_phi");
331  null = ConstantInt::get(date->getType(), 0);
332  if (tuple_is_nullable_) {
333  date_phi->addIncoming(null, entry_block);
334  }
335  if (check_slot_null_indicator_block != NULL) {
336  date_phi->addIncoming(null, check_slot_null_indicator_block);
337  }
338  date_phi->addIncoming(date, get_slot_block);
339 
340  CodegenAnyVal result =
341  CodegenAnyVal::GetNonNullVal(codegen, &builder, type(), "result");
342  result.SetIsNull(is_null_phi);
343  result.SetTimeOfDay(time_of_day_phi);
344  result.SetDate(date_phi);
345  builder.CreateRet(result.value());
346  } else {
347  DCHECK(val != NULL);
348  PHINode* val_phi = builder.CreatePHI(val->getType(), 2, "val_phi");
349  Value* null = Constant::getNullValue(val->getType());
350  if (tuple_is_nullable_) {
351  val_phi->addIncoming(null, entry_block);
352  }
353  if (check_slot_null_indicator_block != NULL) {
354  val_phi->addIncoming(null, check_slot_null_indicator_block);
355  }
356  val_phi->addIncoming(val, get_slot_block);
357 
358  CodegenAnyVal result =
359  CodegenAnyVal::GetNonNullVal(codegen, &builder, type(), "result");
360  result.SetIsNull(is_null_phi);
361  result.SetVal(val_phi);
362  builder.CreateRet(result.value());
363  }
364 
365  *fn = codegen->FinalizeFunction(*fn);
366  codegen->RegisterExprFn(unique_slot_id, *fn);
367  ir_compute_fn_ = *fn;
368  return Status::OK;
369 }
370 
372  DCHECK_EQ(type_.type, TYPE_BOOLEAN);
373  Tuple* t = row->GetTuple(tuple_idx_);
374  if (t == NULL || t->IsNull(null_indicator_offset_)) return BooleanVal::null();
375  return BooleanVal(*reinterpret_cast<bool*>(t->GetSlot(slot_offset_)));
376 }
377 
379  DCHECK_EQ(type_.type, TYPE_TINYINT);
380  Tuple* t = row->GetTuple(tuple_idx_);
381  if (t == NULL || t->IsNull(null_indicator_offset_)) return TinyIntVal::null();
382  return TinyIntVal(*reinterpret_cast<int8_t*>(t->GetSlot(slot_offset_)));
383 }
384 
386  DCHECK_EQ(type_.type, TYPE_SMALLINT);
387  Tuple* t = row->GetTuple(tuple_idx_);
388  if (t == NULL || t->IsNull(null_indicator_offset_)) return SmallIntVal::null();
389  return SmallIntVal(*reinterpret_cast<int16_t*>(t->GetSlot(slot_offset_)));
390 }
391 
393  DCHECK_EQ(type_.type, TYPE_INT);
394  Tuple* t = row->GetTuple(tuple_idx_);
395  if (t == NULL || t->IsNull(null_indicator_offset_)) return IntVal::null();
396  return IntVal(*reinterpret_cast<int32_t*>(t->GetSlot(slot_offset_)));
397 }
398 
400  DCHECK_EQ(type_.type, TYPE_BIGINT);
401  Tuple* t = row->GetTuple(tuple_idx_);
402  if (t == NULL || t->IsNull(null_indicator_offset_)) return BigIntVal::null();
403  return BigIntVal(*reinterpret_cast<int64_t*>(t->GetSlot(slot_offset_)));
404 }
405 
407  DCHECK_EQ(type_.type, TYPE_FLOAT);
408  Tuple* t = row->GetTuple(tuple_idx_);
409  if (t == NULL || t->IsNull(null_indicator_offset_)) return FloatVal::null();
410  return FloatVal(*reinterpret_cast<float*>(t->GetSlot(slot_offset_)));
411 }
412 
414  DCHECK_EQ(type_.type, TYPE_DOUBLE);
415  Tuple* t = row->GetTuple(tuple_idx_);
416  if (t == NULL || t->IsNull(null_indicator_offset_)) return DoubleVal::null();
417  return DoubleVal(*reinterpret_cast<double*>(t->GetSlot(slot_offset_)));
418 }
419 
421  DCHECK(type_.IsStringType());
422  Tuple* t = row->GetTuple(tuple_idx_);
423  if (t == NULL || t->IsNull(null_indicator_offset_)) return StringVal::null();
424  StringVal result;
425  if (type_.type == TYPE_CHAR) {
426  result.ptr = reinterpret_cast<uint8_t*>(
428  result.len = type_.len;
429  } else {
430  StringValue* sv = reinterpret_cast<StringValue*>(t->GetSlot(slot_offset_));
431  sv->ToStringVal(&result);
432  }
433  return result;
434 }
435 
437  DCHECK_EQ(type_.type, TYPE_TIMESTAMP);
438  Tuple* t = row->GetTuple(tuple_idx_);
439  if (t == NULL || t->IsNull(null_indicator_offset_)) return TimestampVal::null();
440  TimestampValue* tv = reinterpret_cast<TimestampValue*>(t->GetSlot(slot_offset_));
441  TimestampVal result;
442  tv->ToTimestampVal(&result);
443  return result;
444 }
445 
447  DCHECK_EQ(type_.type, TYPE_DECIMAL);
448  Tuple* t = row->GetTuple(tuple_idx_);
449  if (t == NULL || t->IsNull(null_indicator_offset_)) return DecimalVal::null();
450  switch (type_.GetByteSize()) {
451  case 4:
452  return DecimalVal(*reinterpret_cast<int32_t*>(t->GetSlot(slot_offset_)));
453  case 8:
454  return DecimalVal(*reinterpret_cast<int64_t*>(t->GetSlot(slot_offset_)));
455  case 16:
456  return DecimalVal(*reinterpret_cast<int128_t*>(t->GetSlot(slot_offset_)));
457  default:
458  DCHECK(false);
459  return DecimalVal::null();
460  }
461 }
462 
463 }
int slot_offset_
Definition: slot-ref.h:57
virtual impala_udf::BooleanVal GetBooleanVal(ExprContext *context, TupleRow *)
Definition: slot-ref.cc:371
llvm::Function * ir_compute_fn_
Cached codegened compute function. Exprs should set this in GetCodegendComputeFn().
Definition: expr.h:299
std::string DebugString() const
Definition: descriptors.cc:370
virtual impala_udf::SmallIntVal GetSmallIntVal(ExprContext *context, TupleRow *)
Definition: slot-ref.cc:385
llvm::PointerType * GetPtrType(llvm::Type *type)
Return a pointer type to 'type'.
Tuple * GetTuple(int tuple_idx)
Definition: tuple-row.h:30
void SetLen(llvm::Value *len)
virtual Status GetCodegendComputeFn(RuntimeState *state, llvm::Function **fn)
Definition: slot-ref.cc:155
virtual impala_udf::TimestampVal GetTimestampVal(ExprContext *context, TupleRow *)
Definition: slot-ref.cc:436
A tuple with 0 materialised slots is represented as NULL.
Definition: tuple.h:48
void SetIsNull(llvm::Value *is_null)
Sets the 'is_null' field of the *Val.
virtual impala_udf::IntVal GetIntVal(ExprContext *context, TupleRow *)
Definition: slot-ref.cc:392
virtual impala_udf::FloatVal GetFloatVal(ExprContext *context, TupleRow *)
Definition: slot-ref.cc:406
#define RETURN_IF_ERROR(stmt)
some generally useful macros
Definition: status.h:242
virtual impala_udf::TinyIntVal GetTinyIntVal(ExprContext *context, TupleRow *)
Definition: slot-ref.cc:378
void SetVal(llvm::Value *val)
void * GetSlot(int offset)
Definition: tuple.h:118
This object has a compatible storage format with boost::ptime.
Definition: udf.h:495
uint8_t * ptr
Definition: udf.h:523
const NullIndicatorOffset & null_indicator_offset() const
Definition: descriptors.h:89
void SetDate(llvm::Value *date)
Setters for TimestampVals.
TupleDescriptor * GetTupleDescriptor(TupleId id) const
Definition: descriptors.cc:437
bool TupleIsNullable(int tuple_idx) const
Return true if the Tuple of the given Tuple index is nullable.
Definition: descriptors.cc:333
static CodegenAnyVal GetNonNullVal(LlvmCodeGen *codegen, LlvmCodeGen::LlvmBuilder *builder, const ColumnType &type, const char *name="")
static const int INVALID_IDX
Definition: descriptors.h:400
virtual impala_udf::StringVal GetStringVal(ExprContext *context, TupleRow *)
Definition: slot-ref.cc:420
bool IsNull(const NullIndicatorOffset &offset) const
Definition: tuple.h:112
void ToTimestampVal(impala_udf::TimestampVal *tv) const
LLVM code generator. This is the top level object to generate jitted code.
Definition: llvm-codegen.h:107
virtual impala_udf::DoubleVal GetDoubleVal(ExprContext *context, TupleRow *)
Definition: slot-ref.cc:413
llvm::Function * CreateIrFunctionPrototype(LlvmCodeGen *codegen, const std::string &name, llvm::Value *(*args)[2])
Definition: expr.cc:456
bool IsStringType() const
Definition: types.h:168
void RegisterExprFn(int64_t id, llvm::Function *function)
Definition: llvm-codegen.h:224
PrimitiveType type
Definition: types.h:60
NullIndicatorOffset null_indicator_offset_
Definition: slot-ref.h:58
void SetPtr(llvm::Value *ptr)
Setters for StringVals.
void SetTimeOfDay(llvm::Value *time_of_day)
int GetByteSize() const
Returns the byte size of this type. Returns 0 for variable length types.
Definition: types.h:178
int len
Only set if type == TYPE_CHAR or type == TYPE_VARCHAR.
Definition: types.h:62
std::string DebugString() const
Definition: descriptors.cc:250
This is the superclass of all expr evaluation nodes.
Definition: expr.h:116
SlotRef(const TExprNode &node)
Definition: slot-ref.cc:31
const DescriptorTbl & desc_tbl() const
Definition: runtime-state.h:93
int GetTupleIdx(TupleId id) const
Returns INVALID_IDX if id not part of this row.
Definition: descriptors.cc:328
const RowDescriptor & row_desc() const
llvm::Type * tinyint_type()
Definition: llvm-codegen.h:386
const ColumnType & type() const
Definition: expr.h:145
llvm::Value * value()
Returns the current type-lowered value.
SlotDescriptor * GetSlotDescriptor(SlotId id) const
Definition: descriptors.cc:447
const SlotId slot_id_
Definition: slot-ref.h:59
virtual int GetSlotIds(std::vector< SlotId > *slot_ids) const
Definition: slot-ref.cc:99
static const Status OK
Definition: status.h:87
static char * CharSlotToPtr(void *slot, const ColumnType &type)
virtual impala_udf::BigIntVal GetBigIntVal(ExprContext *context, TupleRow *)
Definition: slot-ref.cc:399
llvm::Type * GetType(const ColumnType &type)
Returns llvm type for the column type.
uint8_t offset[7 *64-sizeof(uint64_t)]
std::string DebugString() const
Definition: descriptors.cc:75
Status GetCodegen(LlvmCodeGen **codegen, bool initialize=true)
int tuple_offset() const
Definition: descriptors.h:88
const ColumnType type_
analysis is done, types are fixed at this point
Definition: expr.h:289
llvm::Function * GetRegisteredExprFn(int64_t id)
Returns a registered expr function for id or NULL if it does not exist.
Definition: llvm-codegen.h:231
llvm::Function * FinalizeFunction(llvm::Function *function)
bool is_materialized() const
Definition: descriptors.h:92
virtual Status Prepare(RuntimeState *state, const RowDescriptor &row_desc, ExprContext *context)
Definition: slot-ref.cc:63
std::vector< Expr * > children_
Definition: expr.h:290
llvm::Type * int_type()
Definition: llvm-codegen.h:388
virtual impala_udf::DecimalVal GetDecimalVal(ExprContext *context, TupleRow *)
Definition: slot-ref.cc:446
void ToStringVal(impala_udf::StringVal *sv) const
Definition: string-value.h:99
TupleId parent() const
Definition: descriptors.h:79
virtual std::string DebugString() const
Definition: slot-ref.cc:104
llvm::LLVMContext & context()
Definition: llvm-codegen.h:214
virtual std::string DebugString() const
Definition: expr.cc:385
int GetNumChildren() const
Definition: expr.h:143
bool tuple_is_nullable_
Definition: slot-ref.h:60
llvm::PointerType * ptr_type()
Definition: llvm-codegen.h:393