Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
decimal-operators.h
Go to the documentation of this file.
1 // Copyright 2014 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 
16 #ifndef IMPALA_EXPRS_DECIMAL_OPERATORS_H
17 #define IMPALA_EXPRS_DECIMAL_OPERATORS_H
18 
19 #include <stdint.h>
20 #include "runtime/decimal-value.h"
21 #include "udf/udf.h"
22 
23 using namespace impala_udf;
24 
25 namespace impala {
26 
27 class Expr;
28 struct ExprValue;
29 class TupleRow;
30 
34  public:
35  static DecimalVal CastToDecimalVal(FunctionContext*, const DecimalVal&);
36 
37  static DecimalVal CastToDecimalVal(FunctionContext*, const TinyIntVal&);
38  static DecimalVal CastToDecimalVal(FunctionContext*, const SmallIntVal&);
39  static DecimalVal CastToDecimalVal(FunctionContext*, const IntVal&);
40  static DecimalVal CastToDecimalVal(FunctionContext*, const BigIntVal&);
41  static DecimalVal CastToDecimalVal(FunctionContext*, const FloatVal&);
42  static DecimalVal CastToDecimalVal(FunctionContext*, const DoubleVal&);
43  static DecimalVal CastToDecimalVal(FunctionContext*, const StringVal&);
44 
45  static BooleanVal CastToBooleanVal(FunctionContext*, const DecimalVal&);
46  static TinyIntVal CastToTinyIntVal(FunctionContext*, const DecimalVal&);
47  static SmallIntVal CastToSmallIntVal(FunctionContext*, const DecimalVal&);
48  static IntVal CastToIntVal(FunctionContext*, const DecimalVal&);
49  static BigIntVal CastToBigIntVal(FunctionContext*, const DecimalVal&);
50  static FloatVal CastToFloatVal(FunctionContext*, const DecimalVal&);
51  static DoubleVal CastToDoubleVal(FunctionContext*, const DecimalVal&);
52  static StringVal CastToStringVal(FunctionContext*, const DecimalVal&);
53  static TimestampVal CastToTimestampVal(FunctionContext*, const DecimalVal&);
54 
55  static DecimalVal Add_DecimalVal_DecimalVal(
56  FunctionContext*, const DecimalVal&, const DecimalVal&);
57  static DecimalVal Subtract_DecimalVal_DecimalVal(
58  FunctionContext*, const DecimalVal&, const DecimalVal&);
59  static DecimalVal Multiply_DecimalVal_DecimalVal(
60  FunctionContext*, const DecimalVal&, const DecimalVal&);
61  static DecimalVal Divide_DecimalVal_DecimalVal(
62  FunctionContext*, const DecimalVal&, const DecimalVal&);
63  static DecimalVal Mod_DecimalVal_DecimalVal(
64  FunctionContext*, const DecimalVal&, const DecimalVal&);
65 
66  static BooleanVal Eq_DecimalVal_DecimalVal(
67  FunctionContext*, const DecimalVal&, const DecimalVal&);
68  static BooleanVal Ne_DecimalVal_DecimalVal(
69  FunctionContext*, const DecimalVal&, const DecimalVal&);
70  static BooleanVal Ge_DecimalVal_DecimalVal(
71  FunctionContext*, const DecimalVal&, const DecimalVal&);
72  static BooleanVal Gt_DecimalVal_DecimalVal(
73  FunctionContext*, const DecimalVal&, const DecimalVal&);
74  static BooleanVal Le_DecimalVal_DecimalVal(
75  FunctionContext*, const DecimalVal&, const DecimalVal&);
76  static BooleanVal Lt_DecimalVal_DecimalVal(
77  FunctionContext*, const DecimalVal&, const DecimalVal&);
78 
84 
88 
92 
95  ROUND
96  };
97 
100  static DecimalVal RoundDecimal(
101  FunctionContext* context, const DecimalVal& val, const ColumnType& val_type,
102  const ColumnType& output_type, const DecimalRoundOp& op);
103 
106  static DecimalVal RoundDecimal(
107  FunctionContext* context, const DecimalVal& val, const DecimalRoundOp& op);
108 
121  static DecimalVal RoundDecimalNegativeScale(
122  FunctionContext* context, const DecimalVal& val, const ColumnType& val_type,
123  const ColumnType& output_type, const DecimalRoundOp& op, int64_t rounding_scale);
124 
125  private:
127  static DecimalVal IntToDecimalVal(
128  FunctionContext* context, const ColumnType& type, int64_t val);
129  static DecimalVal FloatToDecimalVal(
130  FunctionContext* context, const ColumnType& type, double val);
131 
133  static DecimalVal ScaleDecimalValue(
134  FunctionContext* context, const Decimal4Value& val, const ColumnType& val_type,
135  const ColumnType& output_type);
136  static DecimalVal ScaleDecimalValue(
137  FunctionContext* context, const Decimal8Value& val, const ColumnType& val_type,
138  const ColumnType& output_type);
139  static DecimalVal ScaleDecimalValue(
140  FunctionContext* context, const Decimal16Value& val, const ColumnType& val_type,
141  const ColumnType& output_type);
142 
146  template <typename T>
147  static T RoundDelta(const DecimalValue<T>& v, int src_scale, int target_scale,
148  const DecimalRoundOp& op) {
149  if (op == TRUNCATE) return 0;
150 
151  // Adding more digits, rounding does not apply. New digits are just 0.
152  if (src_scale <= target_scale) return 0;
153 
154  // No need to round for floor() and the value is positive or ceil() and the value
155  // is negative.
156  if (v.value() > 0 && op == FLOOR) return 0;
157  if (v.value() < 0 && op == CEIL) return 0;
158 
159  // We are removing the decimal places. Extract the value of the digits we are
160  // dropping. For example, going from scale 5->2, means we want the last 3 digits.
161  int delta_scale = src_scale - target_scale;
162  DCHECK_GT(delta_scale, 0);
163 
164  // 10^delta_scale
165  T trailing_base = DecimalUtil::GetScaleMultiplier<T>(delta_scale);
166  T trailing_digits = v.value() % trailing_base;
167 
168  // If the trailing digits are zero, never round.
169  if (trailing_digits == 0) return 0;
170 
171  // Trailing digits are non-zero.
172  if (op == CEIL) return 1;
173  if (op == FLOOR) return -1;
174 
175  DCHECK_EQ(op, ROUND);
176  // TODO: > or greater than or equal. i.e. should .500 round up?
177  if (abs(trailing_digits) < trailing_base / 2) return 0;
178  return v.value() < 0 ? -1 : 1;
179  }
180 };
181 
182 }
183 
184 #endif
const T & value() const
int128_t abs(const int128_t &x)
static T RoundDelta(const DecimalValue< T > &v, int src_scale, int target_scale, const DecimalRoundOp &op)
This object has a compatible storage format with boost::ptime.
Definition: udf.h:495
Additional digits are dropped.