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