OmniSciDB  0264ff685a
DateTimeTranslator.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2019 OmniSci, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "DateTimeTranslator.h"
18 
19 #include <boost/algorithm/string.hpp>
20 
21 namespace {
22 
23 std::string from_extract_field(const ExtractField& fieldno) {
24  switch (fieldno) {
25  case kYEAR:
26  return "year";
27  case kQUARTER:
28  return "quarter";
29  case kMONTH:
30  return "month";
31  case kDAY:
32  return "day";
33  case kHOUR:
34  return "hour";
35  case kMINUTE:
36  return "minute";
37  case kSECOND:
38  return "second";
39  case kMILLISECOND:
40  return "millisecond";
41  case kMICROSECOND:
42  return "microsecond";
43  case kNANOSECOND:
44  return "nanosecond";
45  case kDOW:
46  return "dow";
47  case kISODOW:
48  return "isodow";
49  case kDOY:
50  return "doy";
51  case kEPOCH:
52  return "epoch";
53  case kQUARTERDAY:
54  return "quarterday";
55  case kWEEK:
56  return "week";
57  case kWEEK_SUNDAY:
58  return "week_sunday";
59  case kWEEK_SATURDAY:
60  return "week_saturday";
61  case kDATEEPOCH:
62  return "dateepoch";
63  default:
64  UNREACHABLE();
65  }
66  return "";
67 }
68 
69 std::string from_datetrunc_field(const DatetruncField& fieldno) {
70  switch (fieldno) {
71  case dtYEAR:
72  return "year";
73  case dtQUARTER:
74  return "quarter";
75  case dtMONTH:
76  return "month";
77  case dtQUARTERDAY:
78  return "quarterday";
79  case dtDAY:
80  return "day";
81  case dtHOUR:
82  return "hour";
83  case dtMINUTE:
84  return "minute";
85  case dtSECOND:
86  return "second";
87  case dtMILLENNIUM:
88  return "millennium";
89  case dtCENTURY:
90  return "century";
91  case dtDECADE:
92  return "decade";
93  case dtMILLISECOND:
94  return "millisecond";
95  case dtMICROSECOND:
96  return "microsecond";
97  case dtNANOSECOND:
98  return "nanosecond";
99  case dtWEEK:
100  return "week";
101  case dtWEEK_SUNDAY:
102  return "week_sunday";
103  case dtWEEK_SATURDAY:
104  return "week_saturday";
105  case dtINVALID:
106  default:
107  UNREACHABLE();
108  }
109  return "";
110 }
111 
112 } // namespace
113 
115  ExtractField fieldno;
116  if (boost::iequals(field, "year")) {
117  fieldno = kYEAR;
118  } else if (boost::iequals(field, "quarter")) {
119  fieldno = kQUARTER;
120  } else if (boost::iequals(field, "month")) {
121  fieldno = kMONTH;
122  } else if (boost::iequals(field, "day")) {
123  fieldno = kDAY;
124  } else if (boost::iequals(field, "quarterday")) {
125  fieldno = kQUARTERDAY;
126  } else if (boost::iequals(field, "hour")) {
127  fieldno = kHOUR;
128  } else if (boost::iequals(field, "minute")) {
129  fieldno = kMINUTE;
130  } else if (boost::iequals(field, "second")) {
131  fieldno = kSECOND;
132  } else if (boost::iequals(field, "millisecond")) {
133  fieldno = kMILLISECOND;
134  } else if (boost::iequals(field, "microsecond")) {
135  fieldno = kMICROSECOND;
136  } else if (boost::iequals(field, "nanosecond")) {
137  fieldno = kNANOSECOND;
138  } else if (boost::iequals(field, "dow")) {
139  fieldno = kDOW;
140  } else if (boost::iequals(field, "isodow")) {
141  fieldno = kISODOW;
142  } else if (boost::iequals(field, "doy")) {
143  fieldno = kDOY;
144  } else if (boost::iequals(field, "epoch")) {
145  fieldno = kEPOCH;
146  } else if (boost::iequals(field, "week")) {
147  fieldno = kWEEK;
148  } else if (boost::iequals(field, "week_sunday")) {
149  fieldno = kWEEK_SUNDAY;
150  } else if (boost::iequals(field, "week_saturday")) {
151  fieldno = kWEEK_SATURDAY;
152  } else if (boost::iequals(field, "dateepoch")) {
153  fieldno = kDATEEPOCH;
154  } else {
155  throw std::runtime_error("Unsupported field in EXTRACT function " + field);
156  }
157  return fieldno;
158 }
159 
160 std::shared_ptr<Analyzer::Expr> ExtractExpr::generate(
161  const std::shared_ptr<Analyzer::Expr> from_expr,
162  const std::string& field_name) {
163  const auto field = to_extract_field(field_name);
164  return ExtractExpr::generate(from_expr, field);
165 }
166 
167 std::shared_ptr<Analyzer::Expr> ExtractExpr::generate(
168  const std::shared_ptr<Analyzer::Expr> from_expr,
169  const ExtractField& field) {
170  const auto expr_ti = from_expr->get_type_info();
171  if (!expr_ti.is_time()) {
172  throw std::runtime_error(
173  "Only TIME, TIMESTAMP and DATE types can be in EXTRACT function.");
174  }
175  if (expr_ti.get_type() == kTIME && field != kHOUR && field != kMINUTE &&
176  field != kSECOND) {
177  throw std::runtime_error("Cannot EXTRACT " + from_extract_field(field) +
178  " from TIME.");
179  }
180  const SQLTypeInfo ti(kBIGINT, 0, 0, expr_ti.get_notnull());
181  auto constant = std::dynamic_pointer_cast<Analyzer::Constant>(from_expr);
182  if (constant != nullptr) {
183  Datum d;
184  d.bigintval = field == kEPOCH
185  ? floor_div(constant->get_constval().bigintval,
186  get_timestamp_precision_scale(expr_ti.get_dimension()))
187  : getExtractFromTimeConstantValue(
188  constant->get_constval().bigintval, field, expr_ti);
189  constant->set_constval(d);
190  constant->set_type_info(ti);
191  return constant;
192  }
193  return makeExpr<Analyzer::ExtractExpr>(
194  ti, from_expr->get_contains_agg(), field, from_expr->decompress());
195 }
196 
198  DatetruncField fieldno;
199  if (boost::iequals(field, "year")) {
200  fieldno = dtYEAR;
201  } else if (boost::iequals(field, "quarter")) {
202  fieldno = dtQUARTER;
203  } else if (boost::iequals(field, "month")) {
204  fieldno = dtMONTH;
205  } else if (boost::iequals(field, "quarterday")) {
206  fieldno = dtQUARTERDAY;
207  } else if (boost::iequals(field, "day")) {
208  fieldno = dtDAY;
209  } else if (boost::iequals(field, "hour")) {
210  fieldno = dtHOUR;
211  } else if (boost::iequals(field, "minute")) {
212  fieldno = dtMINUTE;
213  } else if (boost::iequals(field, "second")) {
214  fieldno = dtSECOND;
215  } else if (boost::iequals(field, "millennium")) {
216  fieldno = dtMILLENNIUM;
217  } else if (boost::iequals(field, "century")) {
218  fieldno = dtCENTURY;
219  } else if (boost::iequals(field, "decade")) {
220  fieldno = dtDECADE;
221  } else if (boost::iequals(field, "millisecond")) {
222  fieldno = dtMILLISECOND;
223  } else if (boost::iequals(field, "microsecond")) {
224  fieldno = dtMICROSECOND;
225  } else if (boost::iequals(field, "nanosecond")) {
226  fieldno = dtNANOSECOND;
227  } else if (boost::iequals(field, "week")) {
228  fieldno = dtWEEK;
229  } else if (boost::iequals(field, "week_sunday")) {
230  fieldno = dtWEEK_SUNDAY;
231  } else if (boost::iequals(field, "week_saturday")) {
232  fieldno = dtWEEK_SATURDAY;
233  } else {
234  throw std::runtime_error("Invalid field in DATE_TRUNC function " + field);
235  }
236  return fieldno;
237 }
238 
239 std::shared_ptr<Analyzer::Expr> DateTruncExpr::generate(
240  const std::shared_ptr<Analyzer::Expr> from_expr,
241  const std::string& field_name) {
242  const auto field = to_datetrunc_field(field_name);
243  return DateTruncExpr::generate(from_expr, field);
244 }
245 
246 std::shared_ptr<Analyzer::Expr> DateTruncExpr::generate(
247  const std::shared_ptr<Analyzer::Expr> from_expr,
248  const DatetruncField& field) {
249  const auto& expr_ti = from_expr->get_type_info();
250  if (!expr_ti.is_time()) {
251  throw std::runtime_error(
252  "Only TIME, TIMESTAMP and DATE types can be in DATE_TRUNC function.");
253  }
254  if (from_expr->get_type_info().get_type() == kTIME && field != dtHOUR &&
255  field != dtMINUTE && field != dtSECOND) {
256  throw std::runtime_error("Cannot DATE_TRUNC " + from_datetrunc_field(field) +
257  " from TIME.");
258  }
259  SQLTypeInfo ti(kTIMESTAMP, expr_ti.get_dimension(), 0, expr_ti.get_notnull());
260  auto constant = std::dynamic_pointer_cast<Analyzer::Constant>(from_expr);
261  if (constant) {
262  Datum d{0};
263  d.bigintval =
264  getDateTruncConstantValue(constant->get_constval().bigintval, field, expr_ti);
265  constant->set_constval(d);
266  constant->set_type_info(ti);
267  return constant;
268  }
269  return makeExpr<Analyzer::DatetruncExpr>(
270  ti, from_expr->get_contains_agg(), field, from_expr->decompress());
271 }
Definition: sqltypes.h:48
#define UNREACHABLE()
Definition: Logger.h:241
const std::shared_ptr< Analyzer::Expr > generate() const
DEVICE int64_t floor_div(int64_t const dividend, int64_t const divisor)
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
static ExtractField to_extract_field(const std::string &field)
DatetruncField
Definition: DateTruncate.h:27
int64_t bigintval
Definition: sqltypes.h:206
std::string from_extract_field(const ExtractField &fieldno)
std::string from_datetrunc_field(const DatetruncField &fieldno)
ExtractField
constexpr int64_t get_timestamp_precision_scale(const int32_t dimen)
Definition: DateTimeUtils.h:51
static DatetruncField to_datetrunc_field(const std::string &field)
const std::shared_ptr< Analyzer::Expr > generate() const