OmniSciDB  b24e664e58
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
DateTimePlusRewrite.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 MapD Technologies, 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 "DateTimePlusRewrite.h"
18 #include "Execute.h"
19 
20 #include "../Analyzer/Analyzer.h"
21 #include "../Parser/ParserNode.h"
22 #include "Shared/Logger.h"
23 
24 #include "DateTimeTranslator.h"
25 
26 namespace {
27 
29  if (!expr) {
30  return nullptr;
31  }
32  const auto func_oper = dynamic_cast<const Analyzer::FunctionOper*>(expr);
33  if (!func_oper || func_oper->getName() != "TRUNCATE") {
34  return nullptr;
35  }
36  CHECK_EQ(size_t(2), func_oper->getArity());
37  const auto arg = func_oper->getArg(0);
38  const auto& arg_ti = arg->get_type_info();
39  return arg_ti.is_integer() ? arg : nullptr;
40 }
41 
42 bool match_const_integer(const Analyzer::Expr* expr, const int64_t v) {
43  const auto const_expr = dynamic_cast<const Analyzer::Constant*>(expr);
44  if (!const_expr) {
45  return false;
46  }
47  const auto& const_ti = const_expr->get_type_info();
48  if (!const_ti.is_integer()) {
49  return false;
50  }
51  const auto& datum = const_expr->get_constval();
52  switch (const_ti.get_type()) {
53  case kTINYINT:
54  return v == datum.tinyintval;
55  case kSMALLINT:
56  return v == datum.smallintval;
57  case kINT:
58  return v == datum.intval;
59  case kBIGINT:
60  return v == datum.bigintval;
61  default:
62  break;
63  }
64  return false;
65 }
66 
68  const Analyzer::Expr* interval_multiplier,
69  const bool dt_hour) {
70  if (dt_hour) {
71  const auto extract_fn =
72  dynamic_cast<const Analyzer::ExtractExpr*>(interval_multiplier);
73  return (extract_fn && extract_fn->get_field() == kHOUR &&
74  *extract_fn->get_from_expr() == *ts)
75  ? dtHOUR
76  : dtINVALID;
77  }
78  const auto interval_multiplier_fn =
79  remove_truncate_int(remove_cast_to_int(interval_multiplier));
80  if (!interval_multiplier_fn) {
81  return dtINVALID;
82  }
83  const auto interval_multiplier_mul =
84  dynamic_cast<const Analyzer::BinOper*>(interval_multiplier_fn);
85  if (!interval_multiplier_mul || interval_multiplier_mul->get_optype() != kMULTIPLY ||
86  !match_const_integer(interval_multiplier_mul->get_left_operand(), -1)) {
87  return dtINVALID;
88  }
89  const auto extract_minus_one = dynamic_cast<const Analyzer::BinOper*>(
90  interval_multiplier_mul->get_right_operand());
91  if (!extract_minus_one || extract_minus_one->get_optype() != kMINUS ||
92  !match_const_integer(extract_minus_one->get_right_operand(), 1)) {
93  return dtINVALID;
94  }
95  const auto extract_fn =
96  dynamic_cast<const Analyzer::ExtractExpr*>(extract_minus_one->get_left_operand());
97  if (!extract_fn || !(*extract_fn->get_from_expr() == *ts)) {
98  return dtINVALID;
99  }
100  switch (extract_fn->get_field()) {
101  case kDAY:
102  return dtMONTH;
103  case kDOY:
104  return dtYEAR;
105  default:
106  break;
107  }
108  return dtINVALID;
109 }
110 
112  const auto mul_by_interval = dynamic_cast<const Analyzer::BinOper*>(off_arg);
113  if (!mul_by_interval) {
114  return dtINVALID;
115  }
116  auto interval =
117  dynamic_cast<const Analyzer::Constant*>(mul_by_interval->get_right_operand());
118  auto interval_multiplier = mul_by_interval->get_left_operand();
119  if (!interval) {
120  interval =
121  dynamic_cast<const Analyzer::Constant*>(mul_by_interval->get_left_operand());
122  if (!interval) {
123  return dtINVALID;
124  }
125  interval_multiplier = mul_by_interval->get_right_operand();
126  }
127  const auto& interval_ti = interval->get_type_info();
128  if (interval_ti.get_type() != kINTERVAL_DAY_TIME) {
129  return dtINVALID;
130  }
131  const auto& datum = interval->get_constval();
132  switch (datum.bigintval) {
133  case 86400000:
134  return get_dt_field(ts, interval_multiplier, false);
135  case 3600000:
136  return get_dt_field(ts, interval_multiplier, true);
137  default:
138  break;
139  }
140  return dtINVALID;
141 }
142 
143 std::shared_ptr<Analyzer::Expr> remove_cast_to_date(const Analyzer::Expr* expr) {
144  if (!expr) {
145  return nullptr;
146  }
147  const auto uoper = dynamic_cast<const Analyzer::UOper*>(expr);
148  if (!uoper || uoper->get_optype() != kCAST) {
149  return nullptr;
150  }
151  const auto& operand_ti = uoper->get_operand()->get_type_info();
152  const auto& target_ti = uoper->get_type_info();
153  if (operand_ti.get_type() != kTIMESTAMP || target_ti.get_type() != kDATE) {
154  return nullptr;
155  }
156  return uoper->get_own_operand();
157 }
158 
159 } // namespace
160 
161 std::shared_ptr<Analyzer::Expr> rewrite_to_date_trunc(
162  const Analyzer::FunctionOper* dt_plus) {
163  CHECK_EQ("DATETIME_PLUS", dt_plus->getName());
164  CHECK_EQ(size_t(2), dt_plus->getArity());
165  const auto ts = remove_cast_to_date(dt_plus->getArg(0));
166  if (!ts) {
167  return nullptr;
168  }
169  const auto off_arg = dt_plus->getArg(1);
170  const auto dt_field = get_dt_field(ts.get(), off_arg);
171  if (dt_field == dtINVALID) {
172  return nullptr;
173  }
174  return DateTruncExpr::generate(ts, dt_field);
175 }
#define CHECK_EQ(x, y)
Definition: Logger.h:198
size_t getArity() const
Definition: Analyzer.h:1309
const Analyzer::Expr * remove_cast_to_int(const Analyzer::Expr *expr)
Definition: ColumnIR.cpp:527
Definition: sqldefs.h:49
DatetruncField get_dt_field(const Analyzer::Expr *ts, const Analyzer::Expr *interval_multiplier, const bool dt_hour)
DatetruncField
Definition: DateTruncate.h:42
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:78
Definition: sqltypes.h:56
Definition: sqldefs.h:40
const Analyzer::Expr * getArg(const size_t i) const
Definition: Analyzer.h:1311
const Expr * get_operand() const
Definition: Analyzer.h:365
bool match_const_integer(const Analyzer::Expr *expr, const int64_t v)
std::shared_ptr< Analyzer::Expr > remove_cast_to_date(const Analyzer::Expr *expr)
const Analyzer::Expr * remove_truncate_int(const Analyzer::Expr *expr)
Definition: sqltypes.h:48
std::string getName() const
Definition: Analyzer.h:1307
std::shared_ptr< Analyzer::Expr > rewrite_to_date_trunc(const Analyzer::FunctionOper *dt_plus)
const std::shared_ptr< Analyzer::Expr > generate() const