OmniSciDB  06b3bd477c
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 kDATEEPOCH:
58  return "dateepoch";
59  default:
60  UNREACHABLE();
61  }
62  return "";
63 }
64 
65 std::string from_datetrunc_field(const DatetruncField& fieldno) {
66  switch (fieldno) {
67  case dtYEAR:
68  return "year";
69  case dtQUARTER:
70  return "quarter";
71  case dtMONTH:
72  return "month";
73  case dtQUARTERDAY:
74  return "quarterday";
75  case dtDAY:
76  return "day";
77  case dtHOUR:
78  return "hour";
79  case dtMINUTE:
80  return "minute";
81  case dtSECOND:
82  return "second";
83  case dtMILLENNIUM:
84  return "millennium";
85  case dtCENTURY:
86  return "century";
87  case dtDECADE:
88  return "decade";
89  case dtMILLISECOND:
90  return "millisecond";
91  case dtMICROSECOND:
92  return "microsecond";
93  case dtNANOSECOND:
94  return "nanosecond";
95  case dtWEEK:
96  return "week";
97  case dtINVALID:
98  default:
99  UNREACHABLE();
100  }
101  return "";
102 }
103 
104 } // namespace
105 
107  ExtractField fieldno;
108  if (boost::iequals(field, "year")) {
109  fieldno = kYEAR;
110  } else if (boost::iequals(field, "quarter")) {
111  fieldno = kQUARTER;
112  } else if (boost::iequals(field, "month")) {
113  fieldno = kMONTH;
114  } else if (boost::iequals(field, "day")) {
115  fieldno = kDAY;
116  } else if (boost::iequals(field, "quarterday")) {
117  fieldno = kQUARTERDAY;
118  } else if (boost::iequals(field, "hour")) {
119  fieldno = kHOUR;
120  } else if (boost::iequals(field, "minute")) {
121  fieldno = kMINUTE;
122  } else if (boost::iequals(field, "second")) {
123  fieldno = kSECOND;
124  } else if (boost::iequals(field, "millisecond")) {
125  fieldno = kMILLISECOND;
126  } else if (boost::iequals(field, "microsecond")) {
127  fieldno = kMICROSECOND;
128  } else if (boost::iequals(field, "nanosecond")) {
129  fieldno = kNANOSECOND;
130  } else if (boost::iequals(field, "dow")) {
131  fieldno = kDOW;
132  } else if (boost::iequals(field, "isodow")) {
133  fieldno = kISODOW;
134  } else if (boost::iequals(field, "doy")) {
135  fieldno = kDOY;
136  } else if (boost::iequals(field, "epoch")) {
137  fieldno = kEPOCH;
138  } else if (boost::iequals(field, "week")) {
139  fieldno = kWEEK;
140  } else if (boost::iequals(field, "dateepoch")) {
141  fieldno = kDATEEPOCH;
142  } else {
143  throw std::runtime_error("Unsupported field in EXTRACT function " + field);
144  }
145  return fieldno;
146 }
147 
148 std::shared_ptr<Analyzer::Expr> ExtractExpr::generate(
149  const std::shared_ptr<Analyzer::Expr> from_expr,
150  const std::string& field_name) {
151  const auto field = to_extract_field(field_name);
152  return ExtractExpr::generate(from_expr, field);
153 }
154 
155 std::shared_ptr<Analyzer::Expr> ExtractExpr::generate(
156  const std::shared_ptr<Analyzer::Expr> from_expr,
157  const ExtractField& field) {
158  const auto expr_ti = from_expr->get_type_info();
159  if (!expr_ti.is_time()) {
160  throw std::runtime_error(
161  "Only TIME, TIMESTAMP and DATE types can be in EXTRACT function.");
162  }
163  if (expr_ti.get_type() == kTIME && field != kHOUR && field != kMINUTE &&
164  field != kSECOND) {
165  throw std::runtime_error("Cannot EXTRACT " + from_extract_field(field) +
166  " from TIME.");
167  }
168  const SQLTypeInfo ti(kBIGINT, 0, 0, expr_ti.get_notnull());
169  auto constant = std::dynamic_pointer_cast<Analyzer::Constant>(from_expr);
170  if (constant != nullptr) {
171  Datum d;
172  d.bigintval = field == kEPOCH
173  ? floor_div(constant->get_constval().bigintval,
174  get_timestamp_precision_scale(expr_ti.get_dimension()))
176  constant->get_constval().bigintval, field, expr_ti);
177  constant->set_constval(d);
178  constant->set_type_info(ti);
179  return constant;
180  }
181  return makeExpr<Analyzer::ExtractExpr>(
182  ti, from_expr->get_contains_agg(), field, from_expr->decompress());
183 }
184 
186  DatetruncField fieldno;
187  if (boost::iequals(field, "year")) {
188  fieldno = dtYEAR;
189  } else if (boost::iequals(field, "quarter")) {
190  fieldno = dtQUARTER;
191  } else if (boost::iequals(field, "month")) {
192  fieldno = dtMONTH;
193  } else if (boost::iequals(field, "quarterday")) {
194  fieldno = dtQUARTERDAY;
195  } else if (boost::iequals(field, "day")) {
196  fieldno = dtDAY;
197  } else if (boost::iequals(field, "hour")) {
198  fieldno = dtHOUR;
199  } else if (boost::iequals(field, "minute")) {
200  fieldno = dtMINUTE;
201  } else if (boost::iequals(field, "second")) {
202  fieldno = dtSECOND;
203  } else if (boost::iequals(field, "millennium")) {
204  fieldno = dtMILLENNIUM;
205  } else if (boost::iequals(field, "century")) {
206  fieldno = dtCENTURY;
207  } else if (boost::iequals(field, "decade")) {
208  fieldno = dtDECADE;
209  } else if (boost::iequals(field, "millisecond")) {
210  fieldno = dtMILLISECOND;
211  } else if (boost::iequals(field, "microsecond")) {
212  fieldno = dtMICROSECOND;
213  } else if (boost::iequals(field, "nanosecond")) {
214  fieldno = dtNANOSECOND;
215  } else if (boost::iequals(field, "week")) {
216  fieldno = dtWEEK;
217  } else {
218  throw std::runtime_error("Invalid field in DATE_TRUNC function " + field);
219  }
220  return fieldno;
221 }
222 
223 std::shared_ptr<Analyzer::Expr> DateTruncExpr::generate(
224  const std::shared_ptr<Analyzer::Expr> from_expr,
225  const std::string& field_name) {
226  const auto field = to_datetrunc_field(field_name);
227  return DateTruncExpr::generate(from_expr, field);
228 }
229 
230 std::shared_ptr<Analyzer::Expr> DateTruncExpr::generate(
231  const std::shared_ptr<Analyzer::Expr> from_expr,
232  const DatetruncField& field) {
233  const auto& expr_ti = from_expr->get_type_info();
234  if (!expr_ti.is_time()) {
235  throw std::runtime_error(
236  "Only TIME, TIMESTAMP and DATE types can be in DATE_TRUNC function.");
237  }
238  if (from_expr->get_type_info().get_type() == kTIME && field != dtHOUR &&
239  field != dtMINUTE && field != dtSECOND) {
240  throw std::runtime_error("Cannot DATE_TRUNC " + from_datetrunc_field(field) +
241  " from TIME.");
242  }
243  SQLTypeInfo ti(kTIMESTAMP, expr_ti.get_dimension(), 0, expr_ti.get_notnull());
244  auto constant = std::dynamic_pointer_cast<Analyzer::Constant>(from_expr);
245  if (constant) {
246  Datum d{0};
247  d.bigintval =
248  getDateTruncConstantValue(constant->get_constval().bigintval, field, expr_ti);
249  constant->set_constval(d);
250  constant->set_type_info(ti);
251  return constant;
252  }
253  return makeExpr<Analyzer::DatetruncExpr>(
254  ti, from_expr->get_contains_agg(), field, from_expr->decompress());
255 }
Definition: sqltypes.h:50
#define UNREACHABLE()
Definition: Logger.h:241
DEVICE int64_t floor_div(int64_t const dividend, int64_t const divisor)
static int64_t getExtractFromTimeConstantValue(const int64_t &timeval, const ExtractField &field, const SQLTypeInfo &ti)
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:42
const std::shared_ptr< Analyzer::Expr > generate() const
int64_t bigintval
Definition: sqltypes.h:137
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 int64_t getDateTruncConstantValue(const int64_t &timeval, const DatetruncField &field, const SQLTypeInfo &ti)
static DatetruncField to_datetrunc_field(const std::string &field)
const std::shared_ptr< Analyzer::Expr > generate() const