Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
literal.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 "literal.h"
16 
17 #include <sstream>
18 
19 #include "codegen/codegen-anyval.h"
20 #include "codegen/llvm-codegen.h"
21 #include "runtime/runtime-state.h"
22 #include "gen-cpp/Exprs_types.h"
23 
24 #include "common/names.h"
25 
26 using namespace llvm;
27 using namespace impala_udf;
28 
29 namespace impala {
30 
31 Literal::Literal(const TExprNode& node)
32  : Expr(node) {
33  switch (type_.type) {
34  case TYPE_BOOLEAN:
35  DCHECK_EQ(node.node_type, TExprNodeType::BOOL_LITERAL);
36  DCHECK(node.__isset.bool_literal);
37  value_.bool_val = node.bool_literal.value;
38  break;
39  case TYPE_TINYINT:
40  DCHECK_EQ(node.node_type, TExprNodeType::INT_LITERAL);
41  DCHECK(node.__isset.int_literal);
42  value_.tinyint_val = node.int_literal.value;
43  break;
44  case TYPE_SMALLINT:
45  DCHECK_EQ(node.node_type, TExprNodeType::INT_LITERAL);
46  DCHECK(node.__isset.int_literal);
47  value_.smallint_val = node.int_literal.value;
48  break;
49  case TYPE_INT:
50  DCHECK_EQ(node.node_type, TExprNodeType::INT_LITERAL);
51  DCHECK(node.__isset.int_literal);
52  value_.int_val = node.int_literal.value;
53  break;
54  case TYPE_BIGINT:
55  DCHECK_EQ(node.node_type, TExprNodeType::INT_LITERAL);
56  DCHECK(node.__isset.int_literal);
57  value_.bigint_val = node.int_literal.value;
58  break;
59  case TYPE_FLOAT:
60  DCHECK_EQ(node.node_type, TExprNodeType::FLOAT_LITERAL);
61  DCHECK(node.__isset.float_literal);
62  value_.float_val = node.float_literal.value;
63  break;
64  case TYPE_DOUBLE:
65  DCHECK_EQ(node.node_type, TExprNodeType::FLOAT_LITERAL);
66  DCHECK(node.__isset.float_literal);
67  value_.double_val = node.float_literal.value;
68  break;
69  case TYPE_STRING:
70  case TYPE_VARCHAR: {
71  DCHECK_EQ(node.node_type, TExprNodeType::STRING_LITERAL);
72  DCHECK(node.__isset.string_literal);
73  value_ = ExprValue(node.string_literal.value);
74  if (type_.type == TYPE_VARCHAR) {
76  }
77  break;
78  }
79  case TYPE_CHAR: {
80  DCHECK_EQ(node.node_type, TExprNodeType::STRING_LITERAL);
81  DCHECK(node.__isset.string_literal);
82  string str = node.string_literal.value;
83  int str_len = str.size();
84  DCHECK_GT(str_len, 0);
85  str.resize(type_.len);
86  if (str_len < type_.len) {
87  // Pad out literal with spaces.
88  str.replace(str_len, type_.len - str_len, type_.len - str_len, ' ');
89  }
90  value_ = ExprValue(str);
91  break;
92  }
93  case TYPE_DECIMAL: {
94  DCHECK_EQ(node.node_type, TExprNodeType::DECIMAL_LITERAL);
95  DCHECK(node.__isset.decimal_literal);
96  const uint8_t* buffer =
97  reinterpret_cast<const uint8_t*>(&node.decimal_literal.value[0]);
98  int len = node.decimal_literal.value.size();
99  DCHECK_GT(len, 0);
100 
101  switch (type().GetByteSize()) {
102  case 4:
103  DCHECK_LE(len, 4);
105  break;
106  case 8:
107  DCHECK_LE(len, 8);
109  break;
110  case 16:
111  DCHECK_LE(len, 16);
113  break;
114  default:
115  DCHECK(false) << type_.DebugString();
116  }
117  break;
118  }
119  default:
120  DCHECK(false) << "Invalid type: " << TypeToString(type_.type);
121  }
122 }
123 
125  : Expr(type) {
126  DCHECK_EQ(type.type, TYPE_BOOLEAN) << type;
127  value_.bool_val = v;
128 }
129 
131  : Expr(type) {
132  DCHECK_EQ(type.type, TYPE_TINYINT) << type;
133  value_.tinyint_val = v;
134 }
135 
136 Literal::Literal(ColumnType type, int16_t v)
137  : Expr(type) {
138  DCHECK_EQ(type.type, TYPE_SMALLINT) << type;
139  value_.smallint_val = v;
140 }
141 
142 Literal::Literal(ColumnType type, int32_t v)
143  : Expr(type) {
144  DCHECK_EQ(type.type, TYPE_INT) << type;
145  value_.int_val = v;
146 }
147 
148 Literal::Literal(ColumnType type, int64_t v)
149  : Expr(type) {
150  DCHECK_EQ(type.type, TYPE_BIGINT) << type;
151  value_.bigint_val = v;
152 }
153 
155  : Expr(type) {
156  DCHECK_EQ(type.type, TYPE_FLOAT) << type;
157  value_.float_val = v;
158 }
159 
161  : Expr(type) {
162  if (type.type == TYPE_DOUBLE) {
163  value_.double_val = v;
164  } else if (type.type == TYPE_TIMESTAMP) {
166  } else {
167  DCHECK(false) << type.DebugString();
168  }
169 }
170 
171 Literal::Literal(ColumnType type, const string& v)
172  : Expr(type),
173  value_(v) {
174  DCHECK(type.type == TYPE_STRING || type.type == TYPE_CHAR) << type;
175 }
176 
178  : Expr(type),
179  value_(v.DebugString()) {
180  DCHECK(type.type == TYPE_STRING || type.type == TYPE_CHAR) << type;
181 }
182 
183 template<class T>
184 bool ParseString(const string& str, T* val) {
185  istringstream stream(str);
186  stream >> *val;
187  return !stream.fail();
188 }
189 
190 Literal* Literal::CreateLiteral(const ColumnType& type, const string& str) {
191  switch (type.type) {
192  case TYPE_BOOLEAN: {
193  bool v = false;
194  DCHECK(ParseString<bool>(str, &v)) << str;
195  return new Literal(type, v);
196  }
197  case TYPE_TINYINT: {
198  int8_t v = 0;
199  DCHECK(ParseString<int8_t>(str, &v)) << str;
200  return new Literal(type, v);
201  }
202  case TYPE_SMALLINT: {
203  int16_t v = 0;
204  DCHECK(ParseString<int16_t>(str, &v)) << str;
205  return new Literal(type, v);
206  }
207  case TYPE_INT: {
208  int32_t v = 0;
209  DCHECK(ParseString<int32_t>(str, &v)) << str;
210  return new Literal(type, v);
211  }
212  case TYPE_BIGINT: {
213  int64_t v = 0;
214  DCHECK(ParseString<int64_t>(str, &v)) << str;
215  return new Literal(type, v);
216  }
217  case TYPE_FLOAT: {
218  float v = 0;
219  DCHECK(ParseString<float>(str, &v)) << str;
220  return new Literal(type, v);
221  }
222  case TYPE_DOUBLE: {
223  double v = 0;
224  DCHECK(ParseString<double>(str, &v)) << str;
225  return new Literal(type, v);
226  }
227  case TYPE_STRING:
228  case TYPE_VARCHAR:
229  case TYPE_CHAR:
230  return new Literal(type, str);
231  case TYPE_TIMESTAMP: {
232  double v = 0;
233  DCHECK(ParseString<double>(str, &v));
234  return new Literal(type, v);
235  }
236  default:
237  DCHECK(false) << "Invalid type: " << type.DebugString();
238  return NULL;
239  }
240 }
241 
243  DCHECK_EQ(type_.type, TYPE_BOOLEAN) << type_;
244  return BooleanVal(value_.bool_val);
245 }
246 
248  DCHECK_EQ(type_.type, TYPE_TINYINT) << type_;
249  return TinyIntVal(value_.tinyint_val);
250 }
251 
253  DCHECK_EQ(type_.type, TYPE_SMALLINT) << type_;
255 }
256 
258  DCHECK_EQ(type_.type, TYPE_INT) << type_;
259  return IntVal(value_.int_val);
260 }
261 
263  DCHECK_EQ(type_.type, TYPE_BIGINT) << type_;
264  return BigIntVal(value_.bigint_val);
265 }
266 
268  DCHECK_EQ(type_.type, TYPE_FLOAT) << type_;
269  return FloatVal(value_.float_val);
270 }
271 
273  DCHECK_EQ(type_.type, TYPE_DOUBLE) << type_;
274  return DoubleVal(value_.double_val);
275 }
276 
278  DCHECK(type_.IsStringType()) << type_;
279  StringVal result;
280  value_.string_val.ToStringVal(&result);
281  return result;
282 }
283 
285  DCHECK_EQ(type_.type, TYPE_DECIMAL) << type_;
286  switch (type().GetByteSize()) {
287  case 4:
289  case 8:
291  case 16:
293  default:
294  DCHECK(false) << type_.DebugString();
295  }
296  // Quieten GCC.
297  return DecimalVal();
298 }
299 
300 string Literal::DebugString() const {
301  stringstream out;
302  out << "Literal(value=";
303  switch (type_.type) {
304  case TYPE_BOOLEAN:
305  out << value_.bool_val;
306  break;
307  case TYPE_TINYINT:
308  out << value_.tinyint_val;
309  break;
310  case TYPE_SMALLINT:
311  out << value_.smallint_val;
312  break;
313  case TYPE_INT:
314  out << value_.int_val;
315  break;
316  case TYPE_BIGINT:
317  out << value_.bigint_val;
318  break;
319  case TYPE_FLOAT:
320  out << value_.float_val;
321  break;
322  case TYPE_DOUBLE:
323  out << value_.double_val;
324  break;
325  case TYPE_STRING:
326  out << value_.string_val;
327  break;
328  case TYPE_DECIMAL:
329  switch (type().GetByteSize()) {
330  case 4:
331  out << value_.decimal4_val.ToString(type());
332  break;
333  case 8:
334  out << value_.decimal8_val.ToString(type());
335  break;
336  case 16:
337  out << value_.decimal16_val.ToString(type());
338  break;
339  default:
340  DCHECK(false) << type_.DebugString();
341  }
342  break;
343  default:
344  out << "[bad type! " << type_ << "]";
345  }
346  out << Expr::DebugString() << ")";
347  return out.str();
348 }
349 
350 // IR produced for bigint literal 10:
351 //
352 // define { i8, i64 } @Literal(i8* %context, %"class.impala::TupleRow"* %row) {
353 // entry:
354 // ret { i8, i64 } { i8 0, i64 10 }
355 // }
356 Status Literal::GetCodegendComputeFn(RuntimeState* state, llvm::Function** fn) {
357  if (ir_compute_fn_ != NULL) {
358  *fn = ir_compute_fn_;
359  return Status::OK;
360  }
361 
362  DCHECK_EQ(GetNumChildren(), 0);
363  LlvmCodeGen* codegen;
364  RETURN_IF_ERROR(state->GetCodegen(&codegen));
365  Value* args[2];
366  *fn = CreateIrFunctionPrototype(codegen, "Literal", &args);
367  BasicBlock* entry_block = BasicBlock::Create(codegen->context(), "entry", *fn);
368  LlvmCodeGen::LlvmBuilder builder(entry_block);
369 
370  CodegenAnyVal v = CodegenAnyVal::GetNonNullVal(codegen, &builder, type_);
371  switch (type_.type) {
372  case TYPE_BOOLEAN:
374  break;
375  case TYPE_TINYINT:
377  break;
378  case TYPE_SMALLINT:
380  break;
381  case TYPE_INT:
382  v.SetVal(value_.int_val);
383  break;
384  case TYPE_BIGINT:
386  break;
387  case TYPE_FLOAT:
389  break;
390  case TYPE_DOUBLE:
392  break;
393  case TYPE_STRING:
394  case TYPE_VARCHAR:
395  case TYPE_CHAR:
396  v.SetLen(builder.getInt32(value_.string_val.len));
397  v.SetPtr(codegen->CastPtrToLlvmPtr(codegen->ptr_type(), value_.string_val.ptr));
398  break;
399  case TYPE_DECIMAL:
400  switch (type().GetByteSize()) {
401  case 4:
403  break;
404  case 8:
406  break;
407  case 16:
409  break;
410  default:
411  DCHECK(false) << type_.DebugString();
412  }
413  break;
414  default:
415  stringstream ss;
416  ss << "Invalid type: " << type_;
417  DCHECK(false) << ss.str();
418  return Status(ss.str());
419  }
420 
421  builder.CreateRet(v.value());
422  *fn = codegen->FinalizeFunction(*fn);
423  ir_compute_fn_ = *fn;
424  return Status::OK;
425 }
426 
427 }
const T & value() const
virtual impala_udf::IntVal GetIntVal(ExprContext *, TupleRow *)
Definition: literal.cc:257
llvm::Function * ir_compute_fn_
Cached codegened compute function. Exprs should set this in GetCodegendComputeFn().
Definition: expr.h:299
static void DecodeFromFixedLenByteArray(const uint8_t *buffer, int fixed_len_size, T *v)
Definition: decimal-util.h:87
void SetLen(llvm::Value *len)
ExprValue value_
Definition: literal.h:65
#define RETURN_IF_ERROR(stmt)
some generally useful macros
Definition: status.h:242
Decimal8Value decimal8_val
Definition: expr-value.h:36
The materialized value returned by ExprContext::GetValue().
Definition: expr-value.h:25
virtual impala_udf::StringVal GetStringVal(ExprContext *, TupleRow *)
Definition: literal.cc:277
void SetVal(llvm::Value *val)
TimestampValue timestamp_val
Definition: expr-value.h:34
StringValue string_val
Definition: expr-value.h:33
static CodegenAnyVal GetNonNullVal(LlvmCodeGen *codegen, LlvmCodeGen::LlvmBuilder *builder, const ColumnType &type, const char *name="")
virtual impala_udf::SmallIntVal GetSmallIntVal(ExprContext *, TupleRow *)
Definition: literal.cc:252
string TypeToString(PrimitiveType t)
Definition: types.cc:73
static Literal * CreateLiteral(const ColumnType &type, const std::string &str)
Definition: literal.cc:190
virtual Status GetCodegendComputeFn(RuntimeState *state, llvm::Function **fn)
Definition: literal.cc:356
LLVM code generator. This is the top level object to generate jitted code.
Definition: llvm-codegen.h:107
virtual std::string DebugString() const
Definition: literal.cc:300
llvm::Function * CreateIrFunctionPrototype(LlvmCodeGen *codegen, const std::string &name, llvm::Value *(*args)[2])
Definition: expr.cc:456
bool IsStringType() const
Definition: types.h:168
std::string DebugString() const
Definition: types.cc:194
PrimitiveType type
Definition: types.h:60
llvm::Value * CastPtrToLlvmPtr(llvm::Type *type, const void *ptr)
virtual impala_udf::DecimalVal GetDecimalVal(ExprContext *, TupleRow *)
Definition: literal.cc:284
void SetPtr(llvm::Value *ptr)
Setters for StringVals.
std::string DebugString(const T &val)
Definition: udf-debug.h:27
virtual impala_udf::BigIntVal GetBigIntVal(ExprContext *, TupleRow *)
Definition: literal.cc:262
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
This is the superclass of all expr evaluation nodes.
Definition: expr.h:116
virtual impala_udf::BooleanVal GetBooleanVal(ExprContext *, TupleRow *)
Definition: literal.cc:242
virtual impala_udf::FloatVal GetFloatVal(ExprContext *, TupleRow *)
Definition: literal.cc:267
std::string ToString(const ColumnType &type) const
int64_t bigint_val
Definition: expr-value.h:30
const ColumnType & type() const
Definition: expr.h:145
llvm::Value * value()
Returns the current type-lowered value.
Decimal4Value decimal4_val
Definition: expr-value.h:35
Decimal16Value decimal16_val
Definition: expr-value.h:37
static const Status OK
Definition: status.h:87
Status GetCodegen(LlvmCodeGen **codegen, bool initialize=true)
const ColumnType type_
analysis is done, types are fixed at this point
Definition: expr.h:289
int16_t smallint_val
Definition: expr-value.h:28
bool ParseString(const string &str, T *val)
Definition: literal.cc:184
llvm::Function * FinalizeFunction(llvm::Function *function)
void ToStringVal(impala_udf::StringVal *sv) const
Definition: string-value.h:99
llvm::LLVMContext & context()
Definition: llvm-codegen.h:214
virtual impala_udf::TinyIntVal GetTinyIntVal(ExprContext *, TupleRow *)
Definition: literal.cc:247
virtual std::string DebugString() const
Definition: expr.cc:385
virtual impala_udf::DoubleVal GetDoubleVal(ExprContext *, TupleRow *)
Definition: literal.cc:272
int8_t tinyint_val
Definition: expr-value.h:27
Literal(ColumnType type, bool v)
Test ctors.
Definition: literal.cc:124
int GetNumChildren() const
Definition: expr.h:143
llvm::PointerType * ptr_type()
Definition: llvm-codegen.h:393