32 #define RETURN_IF_OVERFLOW(context, overflow) \
34 if (UNLIKELY(overflow)) {\
35 context->AddWarning("Expression overflowed, returning NULL");\
36 return DecimalVal::null();\
43 bool overflow =
false;
62 return DecimalVal::null();
69 bool overflow =
false;
88 return DecimalVal::null();
104 bool overflow =
false;
125 return DecimalVal::null();
134 bool overflow =
false;
155 return DecimalVal::null();
164 bool overflow =
false;
185 return DecimalVal::null();
228 #define CAST_INT_TO_DECIMAL(from_type) \
229 DecimalVal DecimalOperators::CastToDecimalVal( \
230 FunctionContext* context, const from_type& val) { \
231 if (val.is_null) return DecimalVal::null(); \
232 ColumnType type = AnyValUtil::TypeDescToColumnType(context->GetReturnType()); \
233 return IntToDecimalVal(context, type, val.val); \
236 #define CAST_FLOAT_TO_DECIMAL(from_type) \
237 DecimalVal DecimalOperators::CastToDecimalVal( \
238 FunctionContext* context, const from_type& val) { \
239 if (val.is_null) return DecimalVal::null(); \
240 ColumnType type = AnyValUtil::TypeDescToColumnType(context->GetReturnType()); \
241 return FloatToDecimalVal(context, type, val.val); \
244 #define CAST_DECIMAL_TO_INT(to_type) \
245 to_type DecimalOperators::CastTo##to_type( \
246 FunctionContext* context, const DecimalVal& val) { \
247 if (val.is_null) return to_type::null(); \
248 ColumnType type = AnyValUtil::TypeDescToColumnType(*context->GetArgType(0)); \
249 switch (type.GetByteSize()) { \
251 Decimal4Value dv(val.val4); \
252 return to_type(dv.whole_part(type)); \
255 Decimal8Value dv(val.val8); \
256 return to_type(dv.whole_part(type)); \
259 Decimal16Value dv(val.val16); \
260 return to_type(dv.whole_part(type)); \
264 return to_type::null(); \
268 #define CAST_DECIMAL_TO_FLOAT(to_type) \
269 to_type DecimalOperators::CastTo##to_type( \
270 FunctionContext* context, const DecimalVal& val) { \
271 if (val.is_null) return to_type::null(); \
272 ColumnType type = AnyValUtil::TypeDescToColumnType(*context->GetArgType(0)); \
273 switch (type.GetByteSize()) { \
275 Decimal4Value dv(val.val4); \
276 return to_type(dv.ToDouble(type)); \
279 Decimal8Value dv(val.val8); \
280 return to_type(dv.ToDouble(type)); \
283 Decimal16Value dv(val.val16); \
284 return to_type(dv.ToDouble(type)); \
288 return to_type::null(); \
309 DCHECK_GT(rounding_scale, 0);
310 if (val.is_null)
return DecimalVal::null();
314 switch (val_type.GetByteSize()) {
317 result = ScaleDecimalValue(context, val4, val_type, output_type);
322 result = ScaleDecimalValue(context, val8, val_type, output_type);
327 result = ScaleDecimalValue(context, val16, val_type, output_type);
332 return DecimalVal::null();
336 if (result.
is_null)
return result;
339 switch (output_type.GetByteSize()) {
342 int32_t d = RoundDelta(val4, 0, -rounding_scale, op);
343 int32_t base = DecimalUtil::GetScaleMultiplier<int32_t>(rounding_scale);
345 result.
val4 += d * base;
350 int64_t d = RoundDelta(val8, 0, -rounding_scale, op);
351 int64_t base = DecimalUtil::GetScaleMultiplier<int64_t>(rounding_scale);
353 result.
val8 += d * base;
358 int128_t d = RoundDelta(val16, 0, -rounding_scale, op);
359 int128_t base = DecimalUtil::GetScaleMultiplier<int128_t>(rounding_scale);
364 context->AddWarning(
"Expression overflowed, returning NULL");
365 return DecimalVal::null();
367 result.
val16 += delta;
372 return DecimalVal::null();
381 if (val.
is_null)
return DecimalVal::null();
406 return DecimalVal::null();
410 if (result.
is_null)
return result;
414 if (delta == 0)
return result;
421 result.
val16 += delta;
429 return RoundDecimal(context, val, val_type, return_type, op);
442 if (val.
is_null)
return DecimalVal::null();
449 reinterpret_cast<char*
>(val.
ptr), val.
len, type, &result);
455 reinterpret_cast<char*
>(val.
ptr), val.
len, type, &result);
461 reinterpret_cast<char*
>(val.
ptr), val.
len, type, &result);
467 return DecimalVal::null();
475 return DecimalVal::null();
480 if (val.
is_null)
return StringVal::null();
495 return StringVal::null();
498 memcpy(result.ptr, s.c_str(), s.size());
504 if (val.
is_null)
return TimestampVal::null();
529 return TimestampVal::null();
536 if (val.
is_null)
return BooleanVal::null();
548 return BooleanVal::null();
552 #define DECIMAL_ARITHMETIC_OP(FN_NAME, OP_FN) \
553 DecimalVal DecimalOperators::FN_NAME( \
554 FunctionContext* context, const DecimalVal& x, const DecimalVal& y) { \
555 if (x.is_null || y.is_null) return DecimalVal::null(); \
556 bool overflow = false; \
557 ColumnType x_type = AnyValUtil::TypeDescToColumnType(*context->GetArgType(0)); \
558 ColumnType y_type = AnyValUtil::TypeDescToColumnType(*context->GetArgType(1)); \
559 ColumnType return_type = AnyValUtil::TypeDescToColumnType(context->GetReturnType()); \
560 switch (return_type.GetByteSize()) { \
562 Decimal4Value x_val = GetDecimal4Value(x, x_type, &overflow); \
563 Decimal4Value y_val = GetDecimal4Value(y, y_type, &overflow); \
564 Decimal4Value result = x_val.OP_FN<int32_t>( \
565 x_type, y_val, y_type, return_type.scale, &overflow); \
566 DCHECK(!overflow) << "Cannot overflow except with Decimal16Value"; \
567 return DecimalVal(result.value()); \
570 Decimal8Value x_val = GetDecimal8Value(x, x_type, &overflow); \
571 Decimal8Value y_val = GetDecimal8Value(y, y_type, &overflow); \
572 Decimal8Value result = x_val.OP_FN<int64_t>( \
573 x_type, y_val, y_type, return_type.scale, &overflow); \
574 DCHECK(!overflow) << "Cannot overflow except with Decimal16Value"; \
575 return DecimalVal(result.value()); \
578 Decimal16Value x_val = GetDecimal16Value(x, x_type, &overflow); \
579 Decimal16Value y_val = GetDecimal16Value(y, y_type, &overflow); \
580 Decimal16Value result = x_val.OP_FN<int128_t>( \
581 x_type, y_val, y_type, return_type.scale, &overflow); \
582 RETURN_IF_OVERFLOW(context, overflow); \
583 return DecimalVal(result.value()); \
588 return DecimalVal::null(); \
591 #define DECIMAL_ARITHMETIC_OP_CHECK_NAN(FN_NAME, OP_FN) \
592 DecimalVal DecimalOperators::FN_NAME( \
593 FunctionContext* context, const DecimalVal& x, const DecimalVal& y) { \
594 if (x.is_null || y.is_null) return DecimalVal::null(); \
595 bool overflow = false; \
596 bool is_nan = false; \
597 ColumnType x_type = AnyValUtil::TypeDescToColumnType(*context->GetArgType(0)); \
598 ColumnType y_type = AnyValUtil::TypeDescToColumnType(*context->GetArgType(1)); \
599 ColumnType return_type = AnyValUtil::TypeDescToColumnType(context->GetReturnType()); \
600 switch (return_type.GetByteSize()) { \
602 Decimal4Value x_val = GetDecimal4Value(x, x_type, &overflow); \
603 Decimal4Value y_val = GetDecimal4Value(y, y_type, &overflow); \
604 Decimal4Value result = x_val.OP_FN<int32_t>( \
605 x_type, y_val, y_type, return_type.scale, &is_nan, &overflow); \
606 DCHECK(!overflow) << "Cannot overflow except with Decimal16Value"; \
607 if (is_nan) return DecimalVal::null(); \
608 return DecimalVal(result.value()); \
611 Decimal8Value x_val = GetDecimal8Value(x, x_type, &overflow); \
612 Decimal8Value y_val = GetDecimal8Value(y, y_type, &overflow); \
613 Decimal8Value result = x_val.OP_FN<int64_t>( \
614 x_type, y_val, y_type, return_type.scale, &is_nan, &overflow); \
615 DCHECK(!overflow) << "Cannot overflow except with Decimal16Value"; \
616 if (is_nan) return DecimalVal::null(); \
617 return DecimalVal(result.value()); \
620 Decimal16Value x_val = GetDecimal16Value(x, x_type, &overflow); \
621 Decimal16Value y_val = GetDecimal16Value(y, y_type, &overflow); \
622 Decimal16Value result = x_val.OP_FN<int128_t>( \
623 x_type, y_val, y_type, return_type.scale, &is_nan, &overflow); \
624 RETURN_IF_OVERFLOW(context, overflow); \
625 if (is_nan) return DecimalVal::null(); \
626 return DecimalVal(result.value()); \
631 return DecimalVal::null(); \
634 #define DECIMAL_BINARY_OP(FN_NAME, OP_FN) \
635 BooleanVal DecimalOperators::FN_NAME( \
636 FunctionContext* context, const DecimalVal& x, const DecimalVal& y) { \
637 if (x.is_null || y.is_null) return BooleanVal::null(); \
638 bool dummy = false; \
639 ColumnType x_type = AnyValUtil::TypeDescToColumnType(*context->GetArgType(0)); \
640 ColumnType y_type = AnyValUtil::TypeDescToColumnType(*context->GetArgType(1)); \
641 int byte_size = ::max(x_type.GetByteSize(), y_type.GetByteSize()); \
642 switch (byte_size) { \
644 Decimal4Value x_val = GetDecimal4Value(x, x_type, &dummy); \
645 Decimal4Value y_val = GetDecimal4Value(y, y_type, &dummy); \
646 bool result = x_val.OP_FN(x_type, y_val, y_type); \
647 return BooleanVal(result); \
650 Decimal8Value x_val = GetDecimal8Value(x, x_type, &dummy); \
651 Decimal8Value y_val = GetDecimal8Value(y, y_type, &dummy); \
652 bool result = x_val.OP_FN(x_type, y_val, y_type); \
653 return BooleanVal(result); \
656 Decimal16Value x_val = GetDecimal16Value(x, x_type, &dummy); \
657 Decimal16Value y_val = GetDecimal16Value(y, y_type, &dummy); \
658 bool result = x_val.OP_FN(x_type, y_val, y_type); \
659 return BooleanVal(result); \
665 return BooleanVal::null(); \
static DecimalValue FromDouble(const ColumnType &t, double d, bool *overflow)
static TimestampVal CastToTimestampVal(FunctionContext *, const DecimalVal &)
#define DECIMAL_ARITHMETIC_OP(FN_NAME, OP_FN)
const TypeDesc & GetReturnType() const
DecimalValue ScaleTo(const ColumnType &src_type, const ColumnType &dst_type, bool *overflow) const
static StringVal CastToStringVal(FunctionContext *, const DecimalVal &)
int128_t abs(const int128_t &x)
#define CAST_DECIMAL_TO_INT(to_type)
static ColumnType TypeDescToColumnType(const FunctionContext::TypeDesc &type)
static T RoundDelta(const DecimalValue< T > &v, int src_scale, int target_scale, const DecimalRoundOp &op)
DecimalValue< int128_t > Decimal16Value
Decimal8Value ToDecimal8(const Decimal4Value &v, bool *overflow)
static DecimalVal RoundDecimal(FunctionContext *context, const DecimalVal &val, const ColumnType &val_type, const ColumnType &output_type, const DecimalRoundOp &op)
static Decimal4Value GetDecimal4Value(const DecimalVal &val, const ColumnType &type, bool *overflow)
This object has a compatible storage format with boost::ptime.
#define DECIMAL_ARITHMETIC_OP_CHECK_NAN(FN_NAME, OP_FN)
#define RETURN_IF_OVERFLOW(context, overflow)
Decimal16Value ToDecimal16(const Decimal4Value &v, bool *overflow)
static Decimal16Value GetDecimal16Value(const DecimalVal &val, const ColumnType &type, bool *overflow)
#define CAST_FLOAT_TO_DECIMAL(from_type)
static int128_t MAX_UNSCALED_DECIMAL
Maximum absolute value of int128_t that we use. This is 38 digits of 9's.
void ToTimestampVal(impala_udf::TimestampVal *tv) const
Additional digits are dropped.
DecimalValue< int64_t > Decimal8Value
#define CAST_DECIMAL_TO_FLOAT(to_type)
const TypeDesc * GetArgType(int arg_idx) const
static DecimalVal FloatToDecimalVal(FunctionContext *context, const ColumnType &type, double val)
DecimalValue< int32_t > Decimal4Value
int GetByteSize() const
Returns the byte size of this type. Returns 0 for variable length types.
#define CAST_INT_TO_DECIMAL(from_type)
static DecimalValue FromInt(const ColumnType &t, int64_t d, bool *overflow)
Assigns *result as a decimal.
std::string ToString(const ColumnType &type) const
static DecimalVal CastToDecimalVal(FunctionContext *, const DecimalVal &)
static DecimalVal IntToDecimalVal(FunctionContext *context, const ColumnType &type, int64_t val)
Converts 'val' to a DecimalVal according to 'type'. 'type' must be a decimal type.
Decimal4Value ToDecimal4(const Decimal4Value &v, bool *overflow)
static BooleanVal CastToBooleanVal(FunctionContext *, const DecimalVal &)
static DecimalVal ScaleDecimalValue(FunctionContext *context, const Decimal4Value &val, const ColumnType &val_type, const ColumnType &output_type)
Returns the value of 'val' scaled to 'output_type'.
static Decimal8Value GetDecimal8Value(const DecimalVal &val, const ColumnType &type, bool *overflow)
#define DECIMAL_BINARY_OP(FN_NAME, OP_FN)
double ToDouble(const ColumnType &type) const
Returns an approximate double for this decimal.
__int128_t int128_t
We use the c++ int128_t type. This is stored using 16 bytes and very performant.