OmniSciDB  c0231cc57d
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RelAlgTranslator.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2022 HEAVY.AI, 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 "RelAlgTranslator.h"
18 #include "Analyzer/Analyzer.h"
20 #include "DateTimePlusRewrite.h"
21 #include "DateTimeTranslator.h"
23 #include "ExpressionRewrite.h"
26 #include "Parser/ParserNode.h"
27 #include "RelAlgDag.h"
28 #include "ScalarExprVisitor.h"
29 #include "Shared/SqlTypesLayout.h"
30 #include "Shared/likely.h"
31 #include "Shared/scope.h"
32 #include "Shared/thread_count.h"
33 #include "WindowContext.h"
34 
35 #include <future>
36 #include <sstream>
37 
38 extern bool g_enable_watchdog;
39 
41 
42 namespace {
43 
45  const int scale,
46  const int precision) {
47  SQLTypeInfo ti(sql_type, 0, 0, true);
48  if (ti.is_decimal()) {
49  ti.set_scale(scale);
50  ti.set_precision(precision);
51  }
52  return ti;
53 }
54 
55 } // namespace
56 
57 std::pair<std::shared_ptr<Analyzer::Expr>, SQLQualifier>
59  std::shared_ptr<Analyzer::Expr> rhs;
60  SQLQualifier sql_qual{kONE};
61  const auto rex_operator = dynamic_cast<const RexOperator*>(rex_scalar);
62  if (!rex_operator) {
63  return std::make_pair(rhs, sql_qual);
64  }
65  const auto rex_function = dynamic_cast<const RexFunctionOperator*>(rex_operator);
66  const auto qual_str = rex_function ? rex_function->getName() : "";
67  if (qual_str == "PG_ANY"sv || qual_str == "PG_ALL"sv) {
68  CHECK_EQ(size_t(1), rex_function->size());
69  rhs = translateScalarRex(rex_function->getOperand(0));
70  sql_qual = (qual_str == "PG_ANY"sv) ? kANY : kALL;
71  }
72  if (!rhs && rex_operator->getOperator() == kCAST) {
73  CHECK_EQ(size_t(1), rex_operator->size());
74  std::tie(rhs, sql_qual) = getQuantifiedRhs(rex_operator->getOperand(0));
75  }
76  return std::make_pair(rhs, sql_qual);
77 }
78 
79 namespace {
80 
81 std::pair<Datum, bool> datum_from_scalar_tv(const ScalarTargetValue* scalar_tv,
82  const SQLTypeInfo& ti) noexcept {
83  Datum d{0};
84  bool is_null_const{false};
85  switch (ti.get_type()) {
86  case kBOOLEAN: {
87  const auto ival = boost::get<int64_t>(scalar_tv);
88  CHECK(ival);
89  if (*ival == inline_int_null_val(ti)) {
90  is_null_const = true;
91  } else {
92  d.boolval = *ival;
93  }
94  break;
95  }
96  case kTINYINT: {
97  const auto ival = boost::get<int64_t>(scalar_tv);
98  CHECK(ival);
99  if (*ival == inline_int_null_val(ti)) {
100  is_null_const = true;
101  } else {
102  d.tinyintval = *ival;
103  }
104  break;
105  }
106  case kSMALLINT: {
107  const auto ival = boost::get<int64_t>(scalar_tv);
108  CHECK(ival);
109  if (*ival == inline_int_null_val(ti)) {
110  is_null_const = true;
111  } else {
112  d.smallintval = *ival;
113  }
114  break;
115  }
116  case kINT: {
117  const auto ival = boost::get<int64_t>(scalar_tv);
118  CHECK(ival);
119  if (*ival == inline_int_null_val(ti)) {
120  is_null_const = true;
121  } else {
122  d.intval = *ival;
123  }
124  break;
125  }
126  case kDECIMAL:
127  case kNUMERIC:
128  case kBIGINT:
129  case kDATE:
130  case kTIME:
131  case kTIMESTAMP: {
132  const auto ival = boost::get<int64_t>(scalar_tv);
133  CHECK(ival);
134  if (*ival == inline_int_null_val(ti)) {
135  is_null_const = true;
136  } else {
137  d.bigintval = *ival;
138  }
139  break;
140  }
141  case kDOUBLE: {
142  const auto dval = boost::get<double>(scalar_tv);
143  CHECK(dval);
144  if (*dval == inline_fp_null_val(ti)) {
145  is_null_const = true;
146  } else {
147  d.doubleval = *dval;
148  }
149  break;
150  }
151  case kFLOAT: {
152  const auto fval = boost::get<float>(scalar_tv);
153  CHECK(fval);
154  if (*fval == inline_fp_null_val(ti)) {
155  is_null_const = true;
156  } else {
157  d.floatval = *fval;
158  }
159  break;
160  }
161  case kTEXT:
162  case kVARCHAR:
163  case kCHAR: {
164  auto nullable_sptr = boost::get<NullableString>(scalar_tv);
165  CHECK(nullable_sptr);
166  if (boost::get<void*>(nullable_sptr)) {
167  is_null_const = true;
168  } else {
169  auto sptr = boost::get<std::string>(nullable_sptr);
170  d.stringval = new std::string(*sptr);
171  }
172  break;
173  }
174  default:
175  CHECK(false) << "Unhandled type: " << ti.get_type_name();
176  }
177  return {d, is_null_const};
178 }
179 
180 using Handler =
181  std::shared_ptr<Analyzer::Expr> (RelAlgTranslator::*)(RexScalar const*) const;
182 using IndexedHandler = std::pair<std::type_index, Handler>;
183 
184 template <typename... Ts>
185 std::array<IndexedHandler, sizeof...(Ts)> makeHandlers() {
186  return {IndexedHandler{std::type_index(typeid(Ts)),
187  &RelAlgTranslator::translateRexScalar<Ts>}...};
188 }
189 
190 struct ByTypeIndex {
191  std::type_index const type_index_;
192  ByTypeIndex(std::type_info const& type_info)
193  : type_index_(std::type_index(type_info)) {}
194  bool operator()(IndexedHandler const& pair) const { return pair.first == type_index_; }
195 };
196 
197 } // namespace
198 
199 template <>
200 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateRexScalar<RexInput>(
201  RexScalar const* rex) const {
202  return translateInput(static_cast<RexInput const*>(rex));
203 }
204 template <>
205 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateRexScalar<RexLiteral>(
206  RexScalar const* rex) const {
207  return translateLiteral(static_cast<RexLiteral const*>(rex));
208 }
209 template <>
210 std::shared_ptr<Analyzer::Expr>
211 RelAlgTranslator::translateRexScalar<RexWindowFunctionOperator>(
212  RexScalar const* rex) const {
213  return translateWindowFunction(static_cast<RexWindowFunctionOperator const*>(rex));
214 }
215 template <>
216 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateRexScalar<RexFunctionOperator>(
217  RexScalar const* rex) const {
218  return translateFunction(static_cast<RexFunctionOperator const*>(rex));
219 }
220 template <>
221 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateRexScalar<RexOperator>(
222  RexScalar const* rex) const {
223  return translateOper(static_cast<RexOperator const*>(rex));
224 }
225 template <>
226 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateRexScalar<RexCase>(
227  RexScalar const* rex) const {
228  return translateCase(static_cast<RexCase const*>(rex));
229 }
230 template <>
231 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateRexScalar<RexSubQuery>(
232  RexScalar const* rex) const {
233  return translateScalarSubquery(static_cast<RexSubQuery const*>(rex));
234 }
235 
236 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateScalarRex(
237  RexScalar const* rex) const {
238  auto cache_itr = cache_.find(rex);
239  if (cache_itr == cache_.end()) {
240  // Order types from most likely to least as they are compared seriatim.
241  static auto const handlers = makeHandlers<RexInput,
242  RexLiteral,
243  RexOperator,
244  RexCase,
247  RexSubQuery>();
248  static_assert(std::is_trivially_destructible_v<decltype(handlers)>);
249  auto it = std::find_if(handlers.cbegin(), handlers.cend(), ByTypeIndex{typeid(*rex)});
250  CHECK(it != handlers.cend()) << "Unhandled type: " << typeid(*rex).name();
251  // Call handler based on typeid(*rex) and cache the std::shared_ptr<Analyzer::Expr>.
252  auto cached = cache_.emplace(rex, (this->*it->second)(rex));
253  CHECK(cached.second) << "Failed to emplace rex of type " << typeid(*rex).name();
254  cache_itr = cached.first;
255  }
256  return cache_itr->second;
257 }
258 
259 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translate(RexScalar const* rex) const {
260  ScopeGuard clear_cache{[this] { cache_.clear(); }};
261  return translateScalarRex(rex);
262 }
263 
264 namespace {
265 
266 bool is_agg_supported_for_type(const SQLAgg& agg_kind, const SQLTypeInfo& arg_ti) {
267  if ((agg_kind == kMIN || agg_kind == kMAX || agg_kind == kSUM || agg_kind == kAVG) &&
268  !(arg_ti.is_number() || arg_ti.is_boolean() || arg_ti.is_time())) {
269  return false;
270  }
271 
272  return true;
273 }
274 
275 } // namespace
276 
277 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateAggregateRex(
278  const RexAgg* rex,
279  const std::vector<std::shared_ptr<Analyzer::Expr>>& scalar_sources) {
280  SQLAgg agg_kind = rex->getKind();
281  const bool is_distinct = rex->isDistinct();
282  const bool takes_arg{rex->size() > 0};
283  std::shared_ptr<Analyzer::Expr> arg_expr;
284  std::shared_ptr<Analyzer::Constant> arg1; // 2nd aggregate parameter
285  if (takes_arg) {
286  const auto operand = rex->getOperand(0);
287  CHECK_LT(operand, scalar_sources.size());
288  CHECK_LE(rex->size(), 2u);
289  arg_expr = scalar_sources[operand];
290  if (agg_kind == kAPPROX_COUNT_DISTINCT && rex->size() == 2) {
291  arg1 = std::dynamic_pointer_cast<Analyzer::Constant>(
292  scalar_sources[rex->getOperand(1)]);
293  if (!arg1 || arg1->get_type_info().get_type() != kINT ||
294  arg1->get_constval().intval < 1 || arg1->get_constval().intval > 100) {
295  throw std::runtime_error(
296  "APPROX_COUNT_DISTINCT's second parameter should be SMALLINT literal between "
297  "1 and 100");
298  }
299  } else if (agg_kind == kAPPROX_QUANTILE) {
300  if (g_cluster) {
301  throw std::runtime_error(
302  "APPROX_PERCENTILE/MEDIAN is not supported in distributed mode at this "
303  "time.");
304  }
305  // If second parameter is not given then APPROX_MEDIAN is assumed.
306  if (rex->size() == 2) {
307  arg1 = std::dynamic_pointer_cast<Analyzer::Constant>(
308  std::dynamic_pointer_cast<Analyzer::Constant>(
309  scalar_sources[rex->getOperand(1)])
310  ->add_cast(SQLTypeInfo(kDOUBLE)));
311  } else {
312 #ifdef _WIN32
313  Datum median;
314  median.doubleval = 0.5;
315 #else
316  constexpr Datum median{.doubleval = 0.5};
317 #endif
318  arg1 = std::make_shared<Analyzer::Constant>(kDOUBLE, false, median);
319  }
320  }
321  const auto& arg_ti = arg_expr->get_type_info();
322  if (!is_agg_supported_for_type(agg_kind, arg_ti)) {
323  throw std::runtime_error("Aggregate on " + arg_ti.get_type_name() +
324  " is not supported yet.");
325  }
326  }
327  const auto agg_ti = get_agg_type(agg_kind, arg_expr.get());
328  return makeExpr<Analyzer::AggExpr>(agg_ti, agg_kind, arg_expr, is_distinct, arg1);
329 }
330 
331 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateLiteral(
332  const RexLiteral* rex_literal) {
333  auto lit_ti = build_type_info(
334  rex_literal->getType(), rex_literal->getScale(), rex_literal->getPrecision());
335  auto target_ti = build_type_info(rex_literal->getTargetType(),
336  rex_literal->getTargetScale(),
337  rex_literal->getTargetPrecision());
338  switch (rex_literal->getType()) {
339  case kINT:
340  case kBIGINT: {
341  Datum d;
342  d.bigintval = rex_literal->getVal<int64_t>();
343  return makeExpr<Analyzer::Constant>(rex_literal->getType(), false, d);
344  }
345  case kDECIMAL: {
346  const auto val = rex_literal->getVal<int64_t>();
347  const int precision = rex_literal->getPrecision();
348  const int scale = rex_literal->getScale();
349  if (target_ti.is_fp() && !scale) {
350  return make_fp_constant(val, target_ti);
351  }
352  auto lit_expr = scale ? Parser::FixedPtLiteral::analyzeValue(val, scale, precision)
354  return lit_ti != target_ti ? lit_expr->add_cast(target_ti) : lit_expr;
355  }
356  case kTEXT: {
357  return Parser::StringLiteral::analyzeValue(rex_literal->getVal<std::string>(),
358  false);
359  }
360  case kBOOLEAN: {
361  Datum d;
362  d.boolval = rex_literal->getVal<bool>();
363  return makeExpr<Analyzer::Constant>(kBOOLEAN, false, d);
364  }
365  case kDOUBLE: {
366  Datum d;
367  d.doubleval = rex_literal->getVal<double>();
368  auto lit_expr =
369  makeExpr<Analyzer::Constant>(SQLTypeInfo(rex_literal->getType(),
370  rex_literal->getPrecision(),
371  rex_literal->getScale(),
372  false),
373  false,
374  d);
375  return lit_ti != target_ti ? lit_expr->add_cast(target_ti) : lit_expr;
376  }
377  case kINTERVAL_DAY_TIME:
378  case kINTERVAL_YEAR_MONTH: {
379  Datum d;
380  d.bigintval = rex_literal->getVal<int64_t>();
381  return makeExpr<Analyzer::Constant>(rex_literal->getType(), false, d);
382  }
383  case kTIME:
384  case kTIMESTAMP: {
385  Datum d;
386  d.bigintval =
387  rex_literal->getType() == kTIMESTAMP && rex_literal->getPrecision() > 0
388  ? rex_literal->getVal<int64_t>()
389  : rex_literal->getVal<int64_t>() / 1000;
390  return makeExpr<Analyzer::Constant>(
391  SQLTypeInfo(rex_literal->getType(), rex_literal->getPrecision(), 0, false),
392  false,
393  d);
394  }
395  case kDATE: {
396  Datum d;
397  d.bigintval = rex_literal->getVal<int64_t>() * 24 * 3600;
398  return makeExpr<Analyzer::Constant>(rex_literal->getType(), false, d);
399  }
400  case kNULLT: {
401  if (target_ti.is_array()) {
403  // defaulting to valid sub-type for convenience
404  target_ti.set_subtype(kBOOLEAN);
405  return makeExpr<Analyzer::ArrayExpr>(target_ti, args, true);
406  }
407  return makeExpr<Analyzer::Constant>(rex_literal->getTargetType(), true, Datum{0});
408  }
409  default: {
410  LOG(FATAL) << "Unexpected literal type " << lit_ti.get_type_name();
411  }
412  }
413  return nullptr;
414 }
415 
416 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateScalarSubquery(
417  const RexSubQuery* rex_subquery) const {
418  if (just_explain_) {
419  throw std::runtime_error("EXPLAIN is not supported with sub-queries");
420  }
421  CHECK(rex_subquery);
422  auto result = rex_subquery->getExecutionResult();
423  auto row_set = result->getRows();
424  const size_t row_count = row_set->rowCount();
425  if (row_count > size_t(1)) {
426  throw std::runtime_error("Scalar sub-query returned multiple rows");
427  }
428  if (row_count == size_t(0)) {
429  if (row_set->isValidationOnlyRes()) {
430  Datum d{0};
431  return makeExpr<Analyzer::Constant>(rex_subquery->getType(), false, d);
432  }
433  throw std::runtime_error("Scalar sub-query returned no results");
434  }
435  CHECK_EQ(row_count, size_t(1));
436  row_set->moveToBegin();
437  auto first_row = row_set->getNextRow(false, false);
438  CHECK_EQ(first_row.size(), size_t(1));
439  auto scalar_tv = boost::get<ScalarTargetValue>(&first_row[0]);
440  auto ti = rex_subquery->getType();
441  if (ti.is_string()) {
442  throw std::runtime_error("Scalar sub-queries which return strings not supported");
443  }
444  Datum d{0};
445  bool is_null_const{false};
446  std::tie(d, is_null_const) = datum_from_scalar_tv(scalar_tv, ti);
447  return makeExpr<Analyzer::Constant>(ti, is_null_const, d);
448 }
449 
450 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateInput(
451  const RexInput* rex_input) const {
452  const auto source = rex_input->getSourceNode();
453  const auto it_rte_idx = input_to_nest_level_.find(source);
454  CHECK(it_rte_idx != input_to_nest_level_.end())
455  << "Not found in input_to_nest_level_, source="
456  << source->toString(RelRexToStringConfig::defaults());
457  const int rte_idx = it_rte_idx->second;
458  const auto scan_source = dynamic_cast<const RelScan*>(source);
459  const auto& in_metainfo = source->getOutputMetainfo();
460  if (scan_source) {
461  // We're at leaf (scan) level and not supposed to have input metadata,
462  // the name and type information come directly from the catalog.
463  CHECK(in_metainfo.empty());
464  const auto table_desc = scan_source->getTableDescriptor();
465  const auto cd =
466  cat_.getMetadataForColumnBySpi(table_desc->tableId, rex_input->getIndex() + 1);
467  CHECK(cd);
468  auto col_ti = cd->columnType;
469  if (col_ti.is_string()) {
470  col_ti.set_type(kTEXT);
471  }
472  if (cd->isVirtualCol) {
473  // TODO(alex): remove at some point, we only need this fixup for backwards
474  // compatibility with old imported data
475  CHECK_EQ("rowid", cd->columnName);
476  col_ti.set_size(8);
477  }
478  CHECK_LE(static_cast<size_t>(rte_idx), join_types_.size());
479  if (rte_idx > 0 && join_types_[rte_idx - 1] == JoinType::LEFT) {
480  col_ti.set_notnull(false);
481  }
482  return std::make_shared<Analyzer::ColumnVar>(
483  col_ti, table_desc->tableId, cd->columnId, rte_idx);
484  }
485  CHECK(!in_metainfo.empty()) << "for "
486  << source->toString(RelRexToStringConfig::defaults());
487  CHECK_GE(rte_idx, 0);
488  const size_t col_id = rex_input->getIndex();
489  CHECK_LT(col_id, in_metainfo.size());
490  auto col_ti = in_metainfo[col_id].get_type_info();
491 
492  if (join_types_.size() > 0) {
493  CHECK_LE(static_cast<size_t>(rte_idx), join_types_.size());
494  if (rte_idx > 0 && join_types_[rte_idx - 1] == JoinType::LEFT) {
495  col_ti.set_notnull(false);
496  }
497  }
498 
499  return std::make_shared<Analyzer::ColumnVar>(col_ti, -source->getId(), col_id, rte_idx);
500 }
501 
502 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateUoper(
503  const RexOperator* rex_operator) const {
504  CHECK_EQ(size_t(1), rex_operator->size());
505  const auto operand_expr = translateScalarRex(rex_operator->getOperand(0));
506  const auto sql_op = rex_operator->getOperator();
507  switch (sql_op) {
508  case kCAST: {
509  const auto& target_ti = rex_operator->getType();
510  CHECK_NE(kNULLT, target_ti.get_type());
511  const auto& operand_ti = operand_expr->get_type_info();
512  if (operand_ti.is_string() && target_ti.is_string()) {
513  return operand_expr;
514  }
515  if (target_ti.is_time() ||
516  operand_ti
517  .is_string()) { // TODO(alex): check and unify with the rest of the cases
518  // Do not propogate encoding on small dates
519  return target_ti.is_date_in_days()
520  ? operand_expr->add_cast(SQLTypeInfo(kDATE, false))
521  : operand_expr->add_cast(target_ti);
522  }
523  if (!operand_ti.is_string() && target_ti.is_string()) {
524  return operand_expr->add_cast(target_ti);
525  }
526  return std::make_shared<Analyzer::UOper>(target_ti, false, sql_op, operand_expr);
527  }
528  case kENCODE_TEXT: {
529  const auto& target_ti = rex_operator->getType();
530  CHECK_NE(kNULLT, target_ti.get_type());
531  const auto& operand_ti = operand_expr->get_type_info();
532  CHECK(operand_ti.is_string());
533  if (operand_ti.is_dict_encoded_string()) {
534  // No cast needed
535  return operand_expr;
536  }
537  if (operand_expr->get_num_column_vars(true) == 0UL) {
538  return operand_expr;
539  }
540  if (g_cluster) {
541  throw std::runtime_error(
542  "ENCODE_TEXT is not currently supported in distributed mode at this time.");
543  }
544  SQLTypeInfo casted_target_ti = operand_ti;
545  casted_target_ti.set_type(kTEXT);
546  casted_target_ti.set_compression(kENCODING_DICT);
547  casted_target_ti.set_comp_param(TRANSIENT_DICT_ID);
548  casted_target_ti.set_fixed_size();
549  return makeExpr<Analyzer::UOper>(
550  casted_target_ti, operand_expr->get_contains_agg(), kCAST, operand_expr);
551  }
552  case kNOT:
553  case kISNULL: {
554  return std::make_shared<Analyzer::UOper>(kBOOLEAN, sql_op, operand_expr);
555  }
556  case kISNOTNULL: {
557  auto is_null = std::make_shared<Analyzer::UOper>(kBOOLEAN, kISNULL, operand_expr);
558  return std::make_shared<Analyzer::UOper>(kBOOLEAN, kNOT, is_null);
559  }
560  case kMINUS: {
561  const auto& ti = operand_expr->get_type_info();
562  return std::make_shared<Analyzer::UOper>(ti, false, kUMINUS, operand_expr);
563  }
564  case kUNNEST: {
565  const auto& ti = operand_expr->get_type_info();
566  CHECK(ti.is_array());
567  return makeExpr<Analyzer::UOper>(ti.get_elem_type(), false, kUNNEST, operand_expr);
568  }
569  default:
570  CHECK(false);
571  }
572  return nullptr;
573 }
574 
575 namespace {
576 
577 std::shared_ptr<Analyzer::Expr> get_in_values_expr(std::shared_ptr<Analyzer::Expr> arg,
578  const ResultSet& val_set) {
580  return nullptr;
581  }
582  if (val_set.rowCount() > 5000000 && g_enable_watchdog) {
583  throw std::runtime_error(
584  "Unable to handle 'expr IN (subquery)', subquery returned 5M+ rows.");
585  }
586  std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
587  const size_t fetcher_count = cpu_threads();
588  std::vector<std::list<std::shared_ptr<Analyzer::Expr>>> expr_set(
589  fetcher_count, std::list<std::shared_ptr<Analyzer::Expr>>());
590  std::vector<std::future<void>> fetcher_threads;
591  const auto& ti = arg->get_type_info();
592  const auto entry_count = val_set.entryCount();
593  for (size_t i = 0,
594  start_entry = 0,
595  stride = (entry_count + fetcher_count - 1) / fetcher_count;
596  i < fetcher_count && start_entry < entry_count;
597  ++i, start_entry += stride) {
598  const auto end_entry = std::min(start_entry + stride, entry_count);
599  fetcher_threads.push_back(std::async(
601  [&](std::list<std::shared_ptr<Analyzer::Expr>>& in_vals,
602  const size_t start,
603  const size_t end) {
604  for (auto index = start; index < end; ++index) {
605  auto row = val_set.getRowAt(index);
606  if (row.empty()) {
607  continue;
608  }
609  auto scalar_tv = boost::get<ScalarTargetValue>(&row[0]);
610  Datum d{0};
611  bool is_null_const{false};
612  std::tie(d, is_null_const) = datum_from_scalar_tv(scalar_tv, ti);
613  if (ti.is_string() && ti.get_compression() != kENCODING_NONE) {
614  auto ti_none_encoded = ti;
615  ti_none_encoded.set_compression(kENCODING_NONE);
616  auto none_encoded_string =
617  makeExpr<Analyzer::Constant>(ti, is_null_const, d);
618  auto dict_encoded_string = std::make_shared<Analyzer::UOper>(
619  ti, false, kCAST, none_encoded_string);
620  in_vals.push_back(dict_encoded_string);
621  } else {
622  in_vals.push_back(makeExpr<Analyzer::Constant>(ti, is_null_const, d));
623  }
624  }
625  },
626  std::ref(expr_set[i]),
627  start_entry,
628  end_entry));
629  }
630  for (auto& child : fetcher_threads) {
631  child.get();
632  }
633 
634  val_set.moveToBegin();
635  for (auto& exprs : expr_set) {
636  value_exprs.splice(value_exprs.end(), exprs);
637  }
638  return makeExpr<Analyzer::InValues>(arg, value_exprs);
639 }
640 
641 } // namespace
642 
643 // Creates an Analyzer expression for an IN subquery which subsequently goes through the
644 // regular Executor::codegen() mechanism. The creation of the expression out of
645 // subquery's result set is parallelized whenever possible. In addition, take advantage
646 // of additional information that elements in the right hand side are constants; see
647 // getInIntegerSetExpr().
648 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateInOper(
649  const RexOperator* rex_operator) const {
650  if (just_explain_) {
651  throw std::runtime_error("EXPLAIN is not supported with sub-queries");
652  }
653  CHECK(rex_operator->size() == 2);
654  const auto lhs = translateScalarRex(rex_operator->getOperand(0));
655  const auto rhs = rex_operator->getOperand(1);
656  const auto rex_subquery = dynamic_cast<const RexSubQuery*>(rhs);
657  CHECK(rex_subquery);
658  auto ti = lhs->get_type_info();
659  auto result = rex_subquery->getExecutionResult();
660  CHECK(result);
661  auto& row_set = result->getRows();
662  CHECK_EQ(size_t(1), row_set->colCount());
663  const auto& rhs_ti = row_set->getColType(0);
664  if (rhs_ti.get_type() != ti.get_type()) {
665  throw std::runtime_error(
666  "The two sides of the IN operator must have the same type; found " +
667  ti.get_type_name() + " and " + rhs_ti.get_type_name());
668  }
669  row_set->moveToBegin();
670  if (row_set->entryCount() > 10000) {
671  std::shared_ptr<Analyzer::Expr> expr;
672  if ((ti.is_integer() || (ti.is_string() && ti.get_compression() == kENCODING_DICT)) &&
673  !row_set->getQueryMemDesc().didOutputColumnar()) {
674  expr = getInIntegerSetExpr(lhs, *row_set);
675  // Handle the highly unlikely case when the InIntegerSet ended up being tiny.
676  // Just let it fall through the usual InValues path at the end of this method,
677  // its codegen knows to use inline comparisons for few values.
678  if (expr && std::static_pointer_cast<Analyzer::InIntegerSet>(expr)
679  ->get_value_list()
680  .size() <= 100) {
681  expr = nullptr;
682  }
683  } else {
684  expr = get_in_values_expr(lhs, *row_set);
685  }
686  if (expr) {
687  return expr;
688  }
689  }
690  std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
691  while (true) {
692  auto row = row_set->getNextRow(true, false);
693  if (row.empty()) {
694  break;
695  }
696  if (g_enable_watchdog && value_exprs.size() >= 10000) {
697  throw std::runtime_error(
698  "Unable to handle 'expr IN (subquery)', subquery returned 10000+ rows.");
699  }
700  auto scalar_tv = boost::get<ScalarTargetValue>(&row[0]);
701  Datum d{0};
702  bool is_null_const{false};
703  std::tie(d, is_null_const) = datum_from_scalar_tv(scalar_tv, ti);
704  if (ti.is_string() && ti.get_compression() != kENCODING_NONE) {
705  auto ti_none_encoded = ti;
706  ti_none_encoded.set_compression(kENCODING_NONE);
707  auto none_encoded_string = makeExpr<Analyzer::Constant>(ti, is_null_const, d);
708  auto dict_encoded_string =
709  std::make_shared<Analyzer::UOper>(ti, false, kCAST, none_encoded_string);
710  value_exprs.push_back(dict_encoded_string);
711  } else {
712  value_exprs.push_back(makeExpr<Analyzer::Constant>(ti, is_null_const, d));
713  }
714  }
715  return makeExpr<Analyzer::InValues>(lhs, value_exprs);
716 }
717 
718 namespace {
719 
720 const size_t g_max_integer_set_size{1 << 25};
721 
723  std::vector<int64_t>& in_vals,
724  std::atomic<size_t>& total_in_vals_count,
725  const ResultSet* values_rowset,
726  const std::pair<int64_t, int64_t> values_rowset_slice,
727  const StringDictionaryProxy* source_dict,
728  const StringDictionaryProxy* dest_dict,
729  const int64_t needle_null_val) {
730  CHECK(in_vals.empty());
731  bool dicts_are_equal = source_dict == dest_dict;
732  for (auto index = values_rowset_slice.first; index < values_rowset_slice.second;
733  ++index) {
734  const auto row = values_rowset->getOneColRow(index);
735  if (UNLIKELY(!row.valid)) {
736  continue;
737  }
738  if (dicts_are_equal) {
739  in_vals.push_back(row.value);
740  } else {
741  const int string_id =
742  row.value == needle_null_val
743  ? needle_null_val
744  : dest_dict->getIdOfString(source_dict->getString(row.value));
745  if (string_id != StringDictionary::INVALID_STR_ID) {
746  in_vals.push_back(string_id);
747  }
748  }
749  if (UNLIKELY(g_enable_watchdog && (in_vals.size() & 1023) == 0 &&
750  total_in_vals_count.fetch_add(1024) >= g_max_integer_set_size)) {
751  throw std::runtime_error(
752  "Unable to handle 'expr IN (subquery)', subquery returned 30M+ rows.");
753  }
754  }
755 }
756 
757 void fill_integer_in_vals(std::vector<int64_t>& in_vals,
758  std::atomic<size_t>& total_in_vals_count,
759  const ResultSet* values_rowset,
760  const std::pair<int64_t, int64_t> values_rowset_slice) {
761  CHECK(in_vals.empty());
762  for (auto index = values_rowset_slice.first; index < values_rowset_slice.second;
763  ++index) {
764  const auto row = values_rowset->getOneColRow(index);
765  if (row.valid) {
766  in_vals.push_back(row.value);
767  if (UNLIKELY(g_enable_watchdog && (in_vals.size() & 1023) == 0 &&
768  total_in_vals_count.fetch_add(1024) >= g_max_integer_set_size)) {
769  throw std::runtime_error(
770  "Unable to handle 'expr IN (subquery)', subquery returned 30M+ rows.");
771  }
772  }
773  }
774 }
775 
776 // Multi-node counterpart of the other version. Saves round-trips, which is crucial
777 // for a big right-hand side result. It only handles physical string dictionary ids,
778 // therefore it won't be able to handle a right-hand side sub-query with a CASE
779 // returning literals on some branches. That case isn't hard too handle either, but
780 // it's not clear it's actually important in practice.
781 // RelAlgTranslator::getInIntegerSetExpr makes sure, by checking the encodings, that
782 // this function isn't called in such cases.
784  std::vector<int64_t>& in_vals,
785  std::atomic<size_t>& total_in_vals_count,
786  const ResultSet* values_rowset,
787  const std::pair<int64_t, int64_t> values_rowset_slice,
788  const std::vector<LeafHostInfo>& leaf_hosts,
789  const DictRef source_dict_ref,
790  const DictRef dest_dict_ref,
791  const int32_t dest_generation,
792  const int64_t needle_null_val) {
793  CHECK(in_vals.empty());
794  std::vector<int32_t> source_ids;
795  source_ids.reserve(values_rowset->entryCount());
796  bool has_nulls = false;
797  if (source_dict_ref == dest_dict_ref) {
798  in_vals.reserve(values_rowset_slice.second - values_rowset_slice.first +
799  1); // Add 1 to cover interval
800  for (auto index = values_rowset_slice.first; index < values_rowset_slice.second;
801  ++index) {
802  const auto row = values_rowset->getOneColRow(index);
803  if (!row.valid) {
804  continue;
805  }
806  if (row.value != needle_null_val) {
807  in_vals.push_back(row.value);
808  if (UNLIKELY(g_enable_watchdog && (in_vals.size() & 1023) == 0 &&
809  total_in_vals_count.fetch_add(1024) >= g_max_integer_set_size)) {
810  throw std::runtime_error(
811  "Unable to handle 'expr IN (subquery)', subquery returned 30M+ rows.");
812  }
813  } else {
814  has_nulls = true;
815  }
816  }
817  if (has_nulls) {
818  in_vals.push_back(
819  needle_null_val); // we've deduped null values as an optimization, although
820  // this is not required by consumer
821  }
822  return;
823  }
824  // Code path below is for when dictionaries are not shared
825  for (auto index = values_rowset_slice.first; index < values_rowset_slice.second;
826  ++index) {
827  const auto row = values_rowset->getOneColRow(index);
828  if (row.valid) {
829  if (row.value != needle_null_val) {
830  source_ids.push_back(row.value);
831  } else {
832  has_nulls = true;
833  }
834  }
835  }
836  std::vector<int32_t> dest_ids;
837  translate_string_ids(dest_ids,
838  leaf_hosts.front(),
839  dest_dict_ref,
840  source_ids,
841  source_dict_ref,
842  dest_generation);
843  CHECK_EQ(dest_ids.size(), source_ids.size());
844  in_vals.reserve(dest_ids.size() + (has_nulls ? 1 : 0));
845  if (has_nulls) {
846  in_vals.push_back(needle_null_val);
847  }
848  for (const int32_t dest_id : dest_ids) {
849  if (dest_id != StringDictionary::INVALID_STR_ID) {
850  in_vals.push_back(dest_id);
851  if (UNLIKELY(g_enable_watchdog && (in_vals.size() & 1023) == 0 &&
852  total_in_vals_count.fetch_add(1024) >= g_max_integer_set_size)) {
853  throw std::runtime_error(
854  "Unable to handle 'expr IN (subquery)', subquery returned 30M+ rows.");
855  }
856  }
857  }
858 }
859 
860 } // namespace
861 
862 // The typical IN subquery involves either dictionary-encoded strings or integers.
863 // Analyzer::InValues is a very heavy representation of the right hand side of such
864 // a query since we already know the right hand would be a list of Analyzer::Constant
865 // shared pointers. We can avoid the big overhead of each Analyzer::Constant and the
866 // refcounting associated with shared pointers by creating an abbreviated InIntegerSet
867 // representation of the IN expression which takes advantage of the this information.
868 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::getInIntegerSetExpr(
869  std::shared_ptr<Analyzer::Expr> arg,
870  const ResultSet& val_set) const {
872  return nullptr;
873  }
874  std::vector<int64_t> value_exprs;
875  const size_t fetcher_count = cpu_threads();
876  std::vector<std::vector<int64_t>> expr_set(fetcher_count);
877  std::vector<std::future<void>> fetcher_threads;
878  const auto& arg_type = arg->get_type_info();
879  const auto entry_count = val_set.entryCount();
880  CHECK_EQ(size_t(1), val_set.colCount());
881  const auto& col_type = val_set.getColType(0);
882  if (g_cluster && arg_type.is_string() &&
883  (col_type.get_comp_param() <= 0 || arg_type.get_comp_param() <= 0)) {
884  // Skip this case for now, see comment for fill_dictionary_encoded_in_vals.
885  return nullptr;
886  }
887  std::atomic<size_t> total_in_vals_count{0};
888  for (size_t i = 0,
889  start_entry = 0,
890  stride = (entry_count + fetcher_count - 1) / fetcher_count;
891  i < fetcher_count && start_entry < entry_count;
892  ++i, start_entry += stride) {
893  expr_set[i].reserve(entry_count / fetcher_count);
894  const auto end_entry = std::min(start_entry + stride, entry_count);
895  if (arg_type.is_string()) {
896  CHECK_EQ(kENCODING_DICT, arg_type.get_compression());
897  // const int32_t dest_dict_id = arg_type.get_comp_param();
898  // const int32_t source_dict_id = col_type.get_comp_param();
899  const DictRef dest_dict_ref(arg_type.get_comp_param(), cat_.getDatabaseId());
900  const DictRef source_dict_ref(col_type.get_comp_param(), cat_.getDatabaseId());
901  const auto dd = executor_->getStringDictionaryProxy(
902  arg_type.get_comp_param(), val_set.getRowSetMemOwner(), true);
903  const auto sd = executor_->getStringDictionaryProxy(
904  col_type.get_comp_param(), val_set.getRowSetMemOwner(), true);
905  CHECK(sd);
906  const auto needle_null_val = inline_int_null_val(arg_type);
907  fetcher_threads.push_back(std::async(
909  [this,
910  &val_set,
911  &total_in_vals_count,
912  sd,
913  dd,
914  source_dict_ref,
915  dest_dict_ref,
916  needle_null_val](
917  std::vector<int64_t>& in_vals, const size_t start, const size_t end) {
918  if (g_cluster) {
919  CHECK_GE(dd->getGeneration(), 0);
921  total_in_vals_count,
922  &val_set,
923  {start, end},
925  source_dict_ref,
926  dest_dict_ref,
927  dd->getGeneration(),
928  needle_null_val);
929  } else {
931  total_in_vals_count,
932  &val_set,
933  {start, end},
934  sd,
935  dd,
936  needle_null_val);
937  }
938  },
939  std::ref(expr_set[i]),
940  start_entry,
941  end_entry));
942  } else {
943  CHECK(arg_type.is_integer());
944  fetcher_threads.push_back(std::async(
946  [&val_set, &total_in_vals_count](
947  std::vector<int64_t>& in_vals, const size_t start, const size_t end) {
948  fill_integer_in_vals(in_vals, total_in_vals_count, &val_set, {start, end});
949  },
950  std::ref(expr_set[i]),
951  start_entry,
952  end_entry));
953  }
954  }
955  for (auto& child : fetcher_threads) {
956  child.get();
957  }
958 
959  val_set.moveToBegin();
960  value_exprs.reserve(entry_count);
961  for (auto& exprs : expr_set) {
962  value_exprs.insert(value_exprs.end(), exprs.begin(), exprs.end());
963  }
964  return makeExpr<Analyzer::InIntegerSet>(
965  arg, value_exprs, arg_type.get_notnull() && col_type.get_notnull());
966 }
967 
968 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateOper(
969  const RexOperator* rex_operator) const {
970  CHECK_GT(rex_operator->size(), size_t(0));
971  if (rex_operator->size() == 1) {
972  return translateUoper(rex_operator);
973  }
974  const auto sql_op = rex_operator->getOperator();
975  if (sql_op == kIN) {
976  return translateInOper(rex_operator);
977  }
978  if (sql_op == kMINUS || sql_op == kPLUS) {
979  auto date_plus_minus = translateDatePlusMinus(rex_operator);
980  if (date_plus_minus) {
981  return date_plus_minus;
982  }
983  }
984  if (sql_op == kOVERLAPS) {
985  return translateOverlapsOper(rex_operator);
986  } else if (IS_COMPARISON(sql_op)) {
987  auto geo_comp = translateGeoComparison(rex_operator);
988  if (geo_comp) {
989  return geo_comp;
990  }
991  }
992  auto lhs = translateScalarRex(rex_operator->getOperand(0));
993  for (size_t i = 1; i < rex_operator->size(); ++i) {
994  std::shared_ptr<Analyzer::Expr> rhs;
995  SQLQualifier sql_qual{kONE};
996  const auto rhs_op = rex_operator->getOperand(i);
997  std::tie(rhs, sql_qual) = getQuantifiedRhs(rhs_op);
998  if (!rhs) {
999  rhs = translateScalarRex(rhs_op);
1000  }
1001  CHECK(rhs);
1002 
1003  // Pass in executor to get string proxy info if cast needed between
1004  // string columns
1005  lhs = Parser::OperExpr::normalize(sql_op, sql_qual, lhs, rhs, executor_);
1006  }
1007  return lhs;
1008 }
1009 
1010 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateOverlapsOper(
1011  const RexOperator* rex_operator) const {
1012  const auto sql_op = rex_operator->getOperator();
1013  CHECK(sql_op == kOVERLAPS);
1014 
1015  const auto lhs = translateScalarRex(rex_operator->getOperand(0));
1016  const auto lhs_ti = lhs->get_type_info();
1017  if (lhs_ti.is_geometry()) {
1018  return translateGeoOverlapsOper(rex_operator);
1019  } else {
1020  throw std::runtime_error(
1021  "Overlaps equivalence is currently only supported for geospatial types");
1022  }
1023 }
1024 
1025 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateCase(
1026  const RexCase* rex_case) const {
1027  std::shared_ptr<Analyzer::Expr> else_expr;
1028  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1029  expr_list;
1030  for (size_t i = 0; i < rex_case->branchCount(); ++i) {
1031  const auto when_expr = translateScalarRex(rex_case->getWhen(i));
1032  const auto then_expr = translateScalarRex(rex_case->getThen(i));
1033  expr_list.emplace_back(when_expr, then_expr);
1034  }
1035  if (rex_case->getElse()) {
1036  else_expr = translateScalarRex(rex_case->getElse());
1037  }
1038  return Parser::CaseExpr::normalize(expr_list, else_expr, executor_);
1039 }
1040 
1041 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateWidthBucket(
1042  const RexFunctionOperator* rex_function) const {
1043  CHECK(rex_function->size() == 4);
1044  auto target_value = translateScalarRex(rex_function->getOperand(0));
1045  auto lower_bound = translateScalarRex(rex_function->getOperand(1));
1046  auto upper_bound = translateScalarRex(rex_function->getOperand(2));
1047  auto partition_count = translateScalarRex(rex_function->getOperand(3));
1048  if (!partition_count->get_type_info().is_integer()) {
1049  throw std::runtime_error(
1050  "PARTITION_COUNT expression of width_bucket function expects an integer type.");
1051  }
1052  auto check_numeric_type =
1053  [](const std::string& col_name, const Analyzer::Expr* expr, bool allow_null_type) {
1054  if (expr->get_type_info().get_type() == kNULLT) {
1055  if (!allow_null_type) {
1056  throw std::runtime_error(
1057  col_name + " expression of width_bucket function expects non-null type.");
1058  }
1059  return;
1060  }
1061  if (!expr->get_type_info().is_number()) {
1062  throw std::runtime_error(
1063  col_name + " expression of width_bucket function expects a numeric type.");
1064  }
1065  };
1066  // target value may have null value
1067  check_numeric_type("TARGET_VALUE", target_value.get(), true);
1068  check_numeric_type("LOWER_BOUND", lower_bound.get(), false);
1069  check_numeric_type("UPPER_BOUND", upper_bound.get(), false);
1070 
1071  auto cast_to_double_if_necessary = [](std::shared_ptr<Analyzer::Expr> arg) {
1072  const auto& arg_ti = arg->get_type_info();
1073  if (arg_ti.get_type() != kDOUBLE) {
1074  const auto& double_ti = SQLTypeInfo(kDOUBLE, arg_ti.get_notnull());
1075  return arg->add_cast(double_ti);
1076  }
1077  return arg;
1078  };
1079  target_value = cast_to_double_if_necessary(target_value);
1080  lower_bound = cast_to_double_if_necessary(lower_bound);
1081  upper_bound = cast_to_double_if_necessary(upper_bound);
1082  return makeExpr<Analyzer::WidthBucketExpr>(
1083  target_value, lower_bound, upper_bound, partition_count);
1084 }
1085 
1086 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateLike(
1087  const RexFunctionOperator* rex_function) const {
1088  CHECK(rex_function->size() == 2 || rex_function->size() == 3);
1089  const auto arg = translateScalarRex(rex_function->getOperand(0));
1090  const auto like = translateScalarRex(rex_function->getOperand(1));
1091  if (!std::dynamic_pointer_cast<const Analyzer::Constant>(like)) {
1092  throw std::runtime_error("The matching pattern must be a literal.");
1093  }
1094  const auto escape = (rex_function->size() == 3)
1095  ? translateScalarRex(rex_function->getOperand(2))
1096  : nullptr;
1097  const bool is_ilike = rex_function->getName() == "PG_ILIKE"sv;
1098  return Parser::LikeExpr::get(arg, like, escape, is_ilike, false);
1099 }
1100 
1101 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateRegexp(
1102  const RexFunctionOperator* rex_function) const {
1103  CHECK(rex_function->size() == 2 || rex_function->size() == 3);
1104  const auto arg = translateScalarRex(rex_function->getOperand(0));
1105  const auto pattern = translateScalarRex(rex_function->getOperand(1));
1106  if (!std::dynamic_pointer_cast<const Analyzer::Constant>(pattern)) {
1107  throw std::runtime_error("The matching pattern must be a literal.");
1108  }
1109  const auto escape = (rex_function->size() == 3)
1110  ? translateScalarRex(rex_function->getOperand(2))
1111  : nullptr;
1112  return Parser::RegexpExpr::get(arg, pattern, escape, false);
1113 }
1114 
1115 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateLikely(
1116  const RexFunctionOperator* rex_function) const {
1117  CHECK(rex_function->size() == 1);
1118  const auto arg = translateScalarRex(rex_function->getOperand(0));
1119  return makeExpr<Analyzer::LikelihoodExpr>(arg, 0.9375);
1120 }
1121 
1122 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateUnlikely(
1123  const RexFunctionOperator* rex_function) const {
1124  CHECK(rex_function->size() == 1);
1125  const auto arg = translateScalarRex(rex_function->getOperand(0));
1126  return makeExpr<Analyzer::LikelihoodExpr>(arg, 0.0625);
1127 }
1128 
1129 namespace {
1130 
1132  const std::shared_ptr<Analyzer::Constant> literal_expr) {
1133  if (!literal_expr || literal_expr->get_is_null()) {
1134  throw std::runtime_error("The 'DatePart' argument must be a not 'null' literal.");
1135  }
1136 }
1137 
1138 } // namespace
1139 
1140 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateExtract(
1141  const RexFunctionOperator* rex_function) const {
1142  CHECK_EQ(size_t(2), rex_function->size());
1143  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1144  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1146  const auto from_expr = translateScalarRex(rex_function->getOperand(1));
1147  const bool is_date_trunc = rex_function->getName() == "PG_DATE_TRUNC"sv;
1148  if (is_date_trunc) {
1149  return DateTruncExpr::generate(from_expr, *timeunit_lit->get_constval().stringval);
1150  } else {
1151  return ExtractExpr::generate(from_expr, *timeunit_lit->get_constval().stringval);
1152  }
1153 }
1154 
1155 namespace {
1156 
1157 std::shared_ptr<Analyzer::Constant> makeNumericConstant(const SQLTypeInfo& ti,
1158  const long val) {
1159  CHECK(ti.is_number());
1160  Datum datum{0};
1161  switch (ti.get_type()) {
1162  case kTINYINT: {
1163  datum.tinyintval = val;
1164  break;
1165  }
1166  case kSMALLINT: {
1167  datum.smallintval = val;
1168  break;
1169  }
1170  case kINT: {
1171  datum.intval = val;
1172  break;
1173  }
1174  case kBIGINT: {
1175  datum.bigintval = val;
1176  break;
1177  }
1178  case kDECIMAL:
1179  case kNUMERIC: {
1180  datum.bigintval = val * exp_to_scale(ti.get_scale());
1181  break;
1182  }
1183  case kFLOAT: {
1184  datum.floatval = val;
1185  break;
1186  }
1187  case kDOUBLE: {
1188  datum.doubleval = val;
1189  break;
1190  }
1191  default:
1192  CHECK(false);
1193  }
1194  return makeExpr<Analyzer::Constant>(ti, false, datum);
1195 }
1196 
1197 } // namespace
1198 
1199 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateDateadd(
1200  const RexFunctionOperator* rex_function) const {
1201  CHECK_EQ(size_t(3), rex_function->size());
1202  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1203  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1205  const auto number_units = translateScalarRex(rex_function->getOperand(1));
1206  const auto number_units_const =
1207  std::dynamic_pointer_cast<Analyzer::Constant>(number_units);
1208  if (number_units_const && number_units_const->get_is_null()) {
1209  throw std::runtime_error("The 'Interval' argument literal must not be 'null'.");
1210  }
1211  const auto cast_number_units = number_units->add_cast(SQLTypeInfo(kBIGINT, false));
1212  const auto datetime = translateScalarRex(rex_function->getOperand(2));
1213  const auto& datetime_ti = datetime->get_type_info();
1214  if (datetime_ti.get_type() == kTIME) {
1215  throw std::runtime_error("DateAdd operation not supported for TIME.");
1216  }
1217  const auto& field = to_dateadd_field(*timeunit_lit->get_constval().stringval);
1218  const int dim = datetime_ti.get_dimension();
1219  return makeExpr<Analyzer::DateaddExpr>(
1220  SQLTypeInfo(kTIMESTAMP, dim, 0, false), field, cast_number_units, datetime);
1221 }
1222 
1223 namespace {
1224 
1226  CHECK(op == kPLUS);
1227  return "DATETIME_PLUS"s;
1228 }
1229 
1230 } // namespace
1231 
1232 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateDatePlusMinus(
1233  const RexOperator* rex_operator) const {
1234  if (rex_operator->size() != 2) {
1235  return nullptr;
1236  }
1237  const auto datetime = translateScalarRex(rex_operator->getOperand(0));
1238  const auto datetime_ti = datetime->get_type_info();
1239  if (!datetime_ti.is_timestamp() && !datetime_ti.is_date()) {
1240  if (datetime_ti.get_type() == kTIME) {
1241  throw std::runtime_error("DateTime addition/subtraction not supported for TIME.");
1242  }
1243  return nullptr;
1244  }
1245  const auto rhs = translateScalarRex(rex_operator->getOperand(1));
1246  const auto rhs_ti = rhs->get_type_info();
1247  if (rhs_ti.get_type() == kTIMESTAMP || rhs_ti.get_type() == kDATE) {
1248  if (datetime_ti.is_high_precision_timestamp() ||
1249  rhs_ti.is_high_precision_timestamp()) {
1250  throw std::runtime_error(
1251  "High Precision timestamps are not supported for TIMESTAMPDIFF operation. "
1252  "Use "
1253  "DATEDIFF.");
1254  }
1255  auto bigint_ti = SQLTypeInfo(kBIGINT, false);
1256  const auto& rex_operator_ti = rex_operator->getType();
1257  const auto datediff_field =
1258  (rex_operator_ti.get_type() == kINTERVAL_DAY_TIME) ? dtSECOND : dtMONTH;
1259  auto result =
1260  makeExpr<Analyzer::DatediffExpr>(bigint_ti, datediff_field, rhs, datetime);
1261  // multiply 1000 to result since expected result should be in millisecond precision.
1262  if (rex_operator_ti.get_type() == kINTERVAL_DAY_TIME) {
1263  return makeExpr<Analyzer::BinOper>(bigint_ti.get_type(),
1264  kMULTIPLY,
1265  kONE,
1266  result,
1267  makeNumericConstant(bigint_ti, 1000));
1268  } else {
1269  return result;
1270  }
1271  }
1272  const auto op = rex_operator->getOperator();
1273  if (op == kPLUS) {
1274  std::vector<std::shared_ptr<Analyzer::Expr>> args = {datetime, rhs};
1275  auto dt_plus = makeExpr<Analyzer::FunctionOper>(
1276  datetime_ti, get_datetimeplus_rewrite_funcname(op), args);
1277  const auto date_trunc = rewrite_to_date_trunc(dt_plus.get());
1278  if (date_trunc) {
1279  return date_trunc;
1280  }
1281  }
1282  const auto interval = fold_expr(rhs.get());
1283  auto interval_ti = interval->get_type_info();
1284  auto bigint_ti = SQLTypeInfo(kBIGINT, false);
1285  const auto interval_lit = std::dynamic_pointer_cast<Analyzer::Constant>(interval);
1286  if (interval_ti.get_type() == kINTERVAL_DAY_TIME) {
1287  std::shared_ptr<Analyzer::Expr> interval_sec;
1288  if (interval_lit) {
1289  interval_sec =
1290  makeNumericConstant(bigint_ti,
1291  (op == kMINUS ? -interval_lit->get_constval().bigintval
1292  : interval_lit->get_constval().bigintval) /
1293  1000);
1294  } else {
1295  interval_sec = makeExpr<Analyzer::BinOper>(bigint_ti.get_type(),
1296  kDIVIDE,
1297  kONE,
1298  interval,
1299  makeNumericConstant(bigint_ti, 1000));
1300  if (op == kMINUS) {
1301  interval_sec =
1302  std::make_shared<Analyzer::UOper>(bigint_ti, false, kUMINUS, interval_sec);
1303  }
1304  }
1305  return makeExpr<Analyzer::DateaddExpr>(datetime_ti, daSECOND, interval_sec, datetime);
1306  }
1307  CHECK(interval_ti.get_type() == kINTERVAL_YEAR_MONTH);
1308  const auto interval_months = op == kMINUS ? std::make_shared<Analyzer::UOper>(
1309  bigint_ti, false, kUMINUS, interval)
1310  : interval;
1311  return makeExpr<Analyzer::DateaddExpr>(datetime_ti, daMONTH, interval_months, datetime);
1312 }
1313 
1314 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateDatediff(
1315  const RexFunctionOperator* rex_function) const {
1316  CHECK_EQ(size_t(3), rex_function->size());
1317  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1318  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1320  const auto start = translateScalarRex(rex_function->getOperand(1));
1321  const auto end = translateScalarRex(rex_function->getOperand(2));
1322  const auto field = to_datediff_field(*timeunit_lit->get_constval().stringval);
1323  return makeExpr<Analyzer::DatediffExpr>(SQLTypeInfo(kBIGINT, false), field, start, end);
1324 }
1325 
1326 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateDatepart(
1327  const RexFunctionOperator* rex_function) const {
1328  CHECK_EQ(size_t(2), rex_function->size());
1329  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1330  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1332  const auto from_expr = translateScalarRex(rex_function->getOperand(1));
1333  return ExtractExpr::generate(
1334  from_expr, to_datepart_field(*timeunit_lit->get_constval().stringval));
1335 }
1336 
1337 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateLength(
1338  const RexFunctionOperator* rex_function) const {
1339  CHECK_EQ(size_t(1), rex_function->size());
1340  const auto str_arg = translateScalarRex(rex_function->getOperand(0));
1341  return makeExpr<Analyzer::CharLengthExpr>(str_arg->decompress(),
1342  rex_function->getName() == "CHAR_LENGTH"sv);
1343 }
1344 
1345 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateKeyForString(
1346  const RexFunctionOperator* rex_function) const {
1347  const auto& args = translateFunctionArgs(rex_function);
1348  CHECK_EQ(size_t(1), args.size());
1349  const auto expr = dynamic_cast<Analyzer::Expr*>(args[0].get());
1350  if (nullptr == expr || !expr->get_type_info().is_string() ||
1351  expr->get_type_info().is_varlen()) {
1352  throw std::runtime_error(rex_function->getName() +
1353  " expects a dictionary encoded text column.");
1354  }
1355  auto unnest_arg = dynamic_cast<Analyzer::UOper*>(expr);
1356  if (unnest_arg && unnest_arg->get_optype() == SQLOps::kUNNEST) {
1357  throw std::runtime_error(
1358  rex_function->getName() +
1359  " does not support unnest operator as its input expression.");
1360  }
1361  return makeExpr<Analyzer::KeyForStringExpr>(args[0]);
1362 }
1363 
1364 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateSampleRatio(
1365  const RexFunctionOperator* rex_function) const {
1366  CHECK_EQ(size_t(1), rex_function->size());
1367  auto arg = translateScalarRex(rex_function->getOperand(0));
1368  const auto& arg_ti = arg->get_type_info();
1369  if (arg_ti.get_type() != kDOUBLE) {
1370  const auto& double_ti = SQLTypeInfo(kDOUBLE, arg_ti.get_notnull());
1371  arg = arg->add_cast(double_ti);
1372  }
1373  return makeExpr<Analyzer::SampleRatioExpr>(arg);
1374 }
1375 
1376 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateCurrentUser(
1377  const RexFunctionOperator* rex_function) const {
1378  std::string user{"SESSIONLESS_USER"};
1379  if (query_state_) {
1380  user = query_state_->getConstSessionInfo()->get_currentUser().userName;
1381  }
1382  return Parser::UserLiteral::get(user);
1383 }
1384 
1385 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateStringOper(
1386  const RexFunctionOperator* rex_function) const {
1387  const auto func_name = rex_function->getName();
1389  std::ostringstream oss;
1390  oss << "Function " << func_name << " not supported.";
1391  throw std::runtime_error(oss.str());
1392  }
1393  const auto string_op_kind = ::name_to_string_op_kind(func_name);
1394  auto args = translateFunctionArgs(rex_function);
1395  // Used by watchdog later to gate queries based on
1396  if (!args.empty() && !dynamic_cast<const Analyzer::Constant*>(args[0].get())) {
1397  const auto& arg0_ti = args[0]->get_type_info();
1398  if (arg0_ti.is_none_encoded_string()) {
1399  SQLTypeInfo casted_target_ti = arg0_ti;
1400  casted_target_ti.set_type(kTEXT);
1401  casted_target_ti.set_compression(kENCODING_DICT);
1402  casted_target_ti.set_comp_param(TRANSIENT_DICT_ID);
1403  casted_target_ti.set_fixed_size();
1404  args[0] = makeExpr<Analyzer::UOper>(
1405  casted_target_ti, args[0]->get_contains_agg(), kCAST, args[0]);
1406  }
1407  }
1408 
1409  switch (string_op_kind) {
1411  return makeExpr<Analyzer::LowerStringOper>(args);
1413  return makeExpr<Analyzer::UpperStringOper>(args);
1415  return makeExpr<Analyzer::InitCapStringOper>(args);
1417  return makeExpr<Analyzer::ReverseStringOper>(args);
1419  return makeExpr<Analyzer::RepeatStringOper>(args);
1421  return makeExpr<Analyzer::ConcatStringOper>(args);
1422  case SqlStringOpKind::LPAD:
1423  case SqlStringOpKind::RPAD: {
1424  return makeExpr<Analyzer::PadStringOper>(string_op_kind, args);
1425  }
1426  case SqlStringOpKind::TRIM:
1428  case SqlStringOpKind::RTRIM: {
1429  return makeExpr<Analyzer::TrimStringOper>(string_op_kind, args);
1430  }
1432  return makeExpr<Analyzer::SubstringStringOper>(args);
1434  return makeExpr<Analyzer::OverlayStringOper>(args);
1436  return makeExpr<Analyzer::ReplaceStringOper>(args);
1438  return makeExpr<Analyzer::SplitPartStringOper>(args);
1440  return makeExpr<Analyzer::RegexpReplaceStringOper>(args);
1442  return makeExpr<Analyzer::RegexpSubstrStringOper>(args);
1444  return makeExpr<Analyzer::JsonValueStringOper>(args);
1446  return makeExpr<Analyzer::Base64EncodeStringOper>(args);
1448  return makeExpr<Analyzer::Base64DecodeStringOper>(args);
1449  default: {
1450  throw std::runtime_error("Unsupported string function.");
1451  }
1452  }
1453 }
1454 
1456  const RexFunctionOperator* rex_function) const {
1457  const auto ret_ti = rex_function->getType();
1458  const auto arg = translateScalarRex(rex_function->getOperand(0));
1459  const auto arg_ti = arg->get_type_info();
1460  if (!arg_ti.is_array()) {
1461  throw std::runtime_error(rex_function->getName() + " expects an array expression.");
1462  }
1463  if (arg_ti.get_subtype() == kARRAY) {
1464  throw std::runtime_error(rex_function->getName() +
1465  " expects one-dimension array expression.");
1466  }
1467  const auto array_size = arg_ti.get_size();
1468  const auto array_elem_size = arg_ti.get_elem_type().get_array_context_logical_size();
1469 
1470  if (array_size > 0) {
1471  if (array_elem_size <= 0) {
1472  throw std::runtime_error(rex_function->getName() +
1473  ": unexpected array element type.");
1474  }
1475  // Return cardinality of a fixed length array
1476  return makeNumericConstant(ret_ti, array_size / array_elem_size);
1477  }
1478  // Variable length array cardinality will be calculated at runtime
1479  return makeExpr<Analyzer::CardinalityExpr>(arg);
1480 }
1481 
1482 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateItem(
1483  const RexFunctionOperator* rex_function) const {
1484  CHECK_EQ(size_t(2), rex_function->size());
1485  const auto base = translateScalarRex(rex_function->getOperand(0));
1486  const auto index = translateScalarRex(rex_function->getOperand(1));
1487  return makeExpr<Analyzer::BinOper>(
1488  base->get_type_info().get_elem_type(), false, kARRAY_AT, kONE, base, index);
1489 }
1490 
1491 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateCurrentDate() const {
1492  constexpr bool is_null = false;
1493  Datum datum;
1494  datum.bigintval = now_ - now_ % (24 * 60 * 60); // Assumes 0 < now_.
1495  return makeExpr<Analyzer::Constant>(kDATE, is_null, datum);
1496 }
1497 
1498 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateCurrentTime() const {
1499  constexpr bool is_null = false;
1500  Datum datum;
1501  datum.bigintval = now_ % (24 * 60 * 60); // Assumes 0 < now_.
1502  return makeExpr<Analyzer::Constant>(kTIME, is_null, datum);
1503 }
1504 
1505 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateCurrentTimestamp() const {
1507 }
1508 
1509 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateDatetime(
1510  const RexFunctionOperator* rex_function) const {
1511  CHECK_EQ(size_t(1), rex_function->size());
1512  const auto arg = translateScalarRex(rex_function->getOperand(0));
1513  const auto arg_lit = std::dynamic_pointer_cast<Analyzer::Constant>(arg);
1514  const std::string datetime_err{R"(Only DATETIME('NOW') supported for now.)"};
1515  if (!arg_lit || arg_lit->get_is_null()) {
1516  throw std::runtime_error(datetime_err);
1517  }
1518  CHECK(arg_lit->get_type_info().is_string());
1519  if (*arg_lit->get_constval().stringval != "NOW"sv) {
1520  throw std::runtime_error(datetime_err);
1521  }
1522  return translateCurrentTimestamp();
1523 }
1524 
1525 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateAbs(
1526  const RexFunctionOperator* rex_function) const {
1527  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1528  expr_list;
1529  CHECK_EQ(size_t(1), rex_function->size());
1530  const auto operand = translateScalarRex(rex_function->getOperand(0));
1531  const auto& operand_ti = operand->get_type_info();
1532  CHECK(operand_ti.is_number());
1533  const auto zero = makeNumericConstant(operand_ti, 0);
1534  const auto lt_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kLT, kONE, operand, zero);
1535  const auto uminus_operand =
1536  makeExpr<Analyzer::UOper>(operand_ti.get_type(), kUMINUS, operand);
1537  expr_list.emplace_back(lt_zero, uminus_operand);
1538  return makeExpr<Analyzer::CaseExpr>(operand_ti, false, expr_list, operand);
1539 }
1540 
1541 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateSign(
1542  const RexFunctionOperator* rex_function) const {
1543  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1544  expr_list;
1545  CHECK_EQ(size_t(1), rex_function->size());
1546  const auto operand = translateScalarRex(rex_function->getOperand(0));
1547  const auto& operand_ti = operand->get_type_info();
1548  CHECK(operand_ti.is_number());
1549  const auto zero = makeNumericConstant(operand_ti, 0);
1550  const auto lt_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kLT, kONE, operand, zero);
1551  expr_list.emplace_back(lt_zero, makeNumericConstant(operand_ti, -1));
1552  const auto eq_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kEQ, kONE, operand, zero);
1553  expr_list.emplace_back(eq_zero, makeNumericConstant(operand_ti, 0));
1554  const auto gt_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kGT, kONE, operand, zero);
1555  expr_list.emplace_back(gt_zero, makeNumericConstant(operand_ti, 1));
1556  return makeExpr<Analyzer::CaseExpr>(
1557  operand_ti,
1558  false,
1559  expr_list,
1560  makeExpr<Analyzer::Constant>(operand_ti, true, Datum{0}));
1561 }
1562 
1563 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateOffsetInFragment() const {
1564  return makeExpr<Analyzer::OffsetInFragment>();
1565 }
1566 
1568  const RexFunctionOperator* rex_function) const {
1569  if (rex_function->getType().get_subtype() == kNULLT) {
1570  auto sql_type = rex_function->getType();
1571  CHECK(sql_type.get_type() == kARRAY);
1572 
1573  // FIX-ME: Deal with NULL arrays
1574  auto translated_function_args(translateFunctionArgs(rex_function));
1575  if (translated_function_args.size() > 0) {
1576  const auto first_element_logical_type =
1577  get_nullable_logical_type_info(translated_function_args[0]->get_type_info());
1578 
1579  auto diff_elem_itr =
1580  std::find_if(translated_function_args.begin(),
1581  translated_function_args.end(),
1582  [first_element_logical_type](const auto expr) {
1583  return first_element_logical_type !=
1584  get_nullable_logical_type_info(expr->get_type_info());
1585  });
1586  if (diff_elem_itr != translated_function_args.end()) {
1587  throw std::runtime_error(
1588  "Element " +
1589  std::to_string(diff_elem_itr - translated_function_args.begin()) +
1590  " is not of the same type as other elements of the array. Consider casting "
1591  "to force this condition.\nElement Type: " +
1592  get_nullable_logical_type_info((*diff_elem_itr)->get_type_info())
1593  .to_string() +
1594  "\nArray type: " + first_element_logical_type.to_string());
1595  }
1596 
1597  if (first_element_logical_type.is_string() &&
1598  !first_element_logical_type.is_dict_encoded_string()) {
1599  sql_type.set_subtype(first_element_logical_type.get_type());
1600  sql_type.set_compression(kENCODING_FIXED);
1601  } else if (first_element_logical_type.is_dict_encoded_string()) {
1602  sql_type.set_subtype(first_element_logical_type.get_type());
1603  sql_type.set_comp_param(TRANSIENT_DICT_ID);
1604  } else {
1605  sql_type.set_subtype(first_element_logical_type.get_type());
1606  sql_type.set_scale(first_element_logical_type.get_scale());
1607  sql_type.set_precision(first_element_logical_type.get_precision());
1608  }
1609 
1610  return makeExpr<Analyzer::ArrayExpr>(sql_type, translated_function_args);
1611  } else {
1612  // defaulting to valid sub-type for convenience
1613  sql_type.set_subtype(kBOOLEAN);
1614  return makeExpr<Analyzer::ArrayExpr>(sql_type, translated_function_args);
1615  }
1616  } else {
1617  return makeExpr<Analyzer::ArrayExpr>(rex_function->getType(),
1618  translateFunctionArgs(rex_function));
1619  }
1620 }
1621 
1622 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateFunction(
1623  const RexFunctionOperator* rex_function) const {
1624  if (func_resolve(rex_function->getName(), "LIKE"sv, "PG_ILIKE"sv)) {
1625  return translateLike(rex_function);
1626  }
1627  if (rex_function->getName() == "REGEXP_LIKE"sv) {
1628  return translateRegexp(rex_function);
1629  }
1630  if (rex_function->getName() == "LIKELY"sv) {
1631  return translateLikely(rex_function);
1632  }
1633  if (rex_function->getName() == "UNLIKELY"sv) {
1634  return translateUnlikely(rex_function);
1635  }
1636  if (func_resolve(rex_function->getName(), "PG_EXTRACT"sv, "PG_DATE_TRUNC"sv)) {
1637  return translateExtract(rex_function);
1638  }
1639  if (rex_function->getName() == "DATEADD"sv) {
1640  return translateDateadd(rex_function);
1641  }
1642  if (rex_function->getName() == "DATEDIFF"sv) {
1643  return translateDatediff(rex_function);
1644  }
1645  if (rex_function->getName() == "DATEPART"sv) {
1646  return translateDatepart(rex_function);
1647  }
1648  if (func_resolve(rex_function->getName(), "LENGTH"sv, "CHAR_LENGTH"sv)) {
1649  return translateLength(rex_function);
1650  }
1651  if (rex_function->getName() == "KEY_FOR_STRING"sv) {
1652  return translateKeyForString(rex_function);
1653  }
1654  if (rex_function->getName() == "WIDTH_BUCKET"sv) {
1655  return translateWidthBucket(rex_function);
1656  }
1657  if (rex_function->getName() == "SAMPLE_RATIO"sv) {
1658  return translateSampleRatio(rex_function);
1659  }
1660  if (rex_function->getName() == "CURRENT_USER"sv) {
1661  return translateCurrentUser(rex_function);
1662  }
1663  if (func_resolve(rex_function->getName(),
1664  "LOWER"sv,
1665  "UPPER"sv,
1666  "INITCAP"sv,
1667  "REVERSE"sv,
1668  "REPEAT"sv,
1669  "||"sv,
1670  "LPAD"sv,
1671  "RPAD"sv,
1672  "TRIM"sv,
1673  "LTRIM"sv,
1674  "RTRIM"sv,
1675  "SUBSTRING"sv,
1676  "OVERLAY"sv,
1677  "REPLACE"sv,
1678  "SPLIT_PART"sv,
1679  "REGEXP_REPLACE"sv,
1680  "REGEXP_SUBSTR"sv,
1681  "REGEXP_MATCH"sv,
1682  "JSON_VALUE"sv,
1683  "BASE64_ENCODE"sv,
1684  "BASE64_DECODE"sv)) {
1685  return translateStringOper(rex_function);
1686  }
1687  if (func_resolve(rex_function->getName(), "CARDINALITY"sv, "ARRAY_LENGTH"sv)) {
1688  return translateCardinality(rex_function);
1689  }
1690  if (rex_function->getName() == "ITEM"sv) {
1691  return translateItem(rex_function);
1692  }
1693  if (rex_function->getName() == "CURRENT_DATE"sv) {
1694  return translateCurrentDate();
1695  }
1696  if (rex_function->getName() == "CURRENT_TIME"sv) {
1697  return translateCurrentTime();
1698  }
1699  if (rex_function->getName() == "CURRENT_TIMESTAMP"sv) {
1700  return translateCurrentTimestamp();
1701  }
1702  if (rex_function->getName() == "NOW"sv) {
1703  return translateCurrentTimestamp();
1704  }
1705  if (rex_function->getName() == "DATETIME"sv) {
1706  return translateDatetime(rex_function);
1707  }
1708  if (func_resolve(rex_function->getName(), "usTIMESTAMP"sv, "nsTIMESTAMP"sv)) {
1709  return translateHPTLiteral(rex_function);
1710  }
1711  if (rex_function->getName() == "ABS"sv) {
1712  return translateAbs(rex_function);
1713  }
1714  if (rex_function->getName() == "SIGN"sv) {
1715  return translateSign(rex_function);
1716  }
1717  if (func_resolve(rex_function->getName(), "CEIL"sv, "FLOOR"sv)) {
1718  return makeExpr<Analyzer::FunctionOperWithCustomTypeHandling>(
1719  rex_function->getType(),
1720  rex_function->getName(),
1721  translateFunctionArgs(rex_function));
1722  } else if (rex_function->getName() == "ROUND"sv) {
1723  std::vector<std::shared_ptr<Analyzer::Expr>> args =
1724  translateFunctionArgs(rex_function);
1725 
1726  if (rex_function->size() == 1) {
1727  // push a 0 constant if 2nd operand is missing.
1728  // this needs to be done as calcite returns
1729  // only the 1st operand without defaulting the 2nd one
1730  // when the user did not specify the 2nd operand.
1731  SQLTypes t = kSMALLINT;
1732  Datum d;
1733  d.smallintval = 0;
1734  args.push_back(makeExpr<Analyzer::Constant>(t, false, d));
1735  }
1736 
1737  // make sure we have only 2 operands
1738  CHECK(args.size() == 2);
1739 
1740  if (!args[0]->get_type_info().is_number()) {
1741  throw std::runtime_error("Only numeric 1st operands are supported");
1742  }
1743 
1744  // the 2nd operand does not need to be a constant
1745  // it can happily reference another integer column
1746  if (!args[1]->get_type_info().is_integer()) {
1747  throw std::runtime_error("Only integer 2nd operands are supported");
1748  }
1749 
1750  // Calcite may upcast decimals in a way that is
1751  // incompatible with the extension function input. Play it safe and stick with the
1752  // argument type instead.
1753  const SQLTypeInfo ret_ti = args[0]->get_type_info().is_decimal()
1754  ? args[0]->get_type_info()
1755  : rex_function->getType();
1756 
1757  return makeExpr<Analyzer::FunctionOperWithCustomTypeHandling>(
1758  ret_ti, rex_function->getName(), args);
1759  }
1760  if (rex_function->getName() == "DATETIME_PLUS"sv) {
1761  auto dt_plus = makeExpr<Analyzer::FunctionOper>(rex_function->getType(),
1762  rex_function->getName(),
1763  translateFunctionArgs(rex_function));
1764  const auto date_trunc = rewrite_to_date_trunc(dt_plus.get());
1765  if (date_trunc) {
1766  return date_trunc;
1767  }
1768  return translateDateadd(rex_function);
1769  }
1770  if (rex_function->getName() == "/INT"sv) {
1771  CHECK_EQ(size_t(2), rex_function->size());
1772  std::shared_ptr<Analyzer::Expr> lhs = translateScalarRex(rex_function->getOperand(0));
1773  std::shared_ptr<Analyzer::Expr> rhs = translateScalarRex(rex_function->getOperand(1));
1774  const auto rhs_lit = std::dynamic_pointer_cast<Analyzer::Constant>(rhs);
1775  return Parser::OperExpr::normalize(kDIVIDE, kONE, lhs, rhs);
1776  }
1777  if (rex_function->getName() == "Reinterpret"sv) {
1778  CHECK_EQ(size_t(1), rex_function->size());
1779  return translateScalarRex(rex_function->getOperand(0));
1780  }
1781  if (func_resolve(rex_function->getName(),
1782  "ST_X"sv,
1783  "ST_Y"sv,
1784  "ST_XMin"sv,
1785  "ST_YMin"sv,
1786  "ST_XMax"sv,
1787  "ST_YMax"sv,
1788  "ST_NRings"sv,
1789  "ST_NPoints"sv,
1790  "ST_Length"sv,
1791  "ST_Perimeter"sv,
1792  "ST_Area"sv,
1793  "ST_SRID"sv,
1794  "HeavyDB_Geo_PolyBoundsPtr"sv,
1795  "HeavyDB_Geo_PolyRenderGroup"sv)) {
1796  CHECK_EQ(rex_function->size(), size_t(1));
1797  return translateUnaryGeoFunction(rex_function);
1798  }
1799  if (func_resolve(rex_function->getName(), "ST_ConvexHull"sv)) {
1800  CHECK_EQ(rex_function->size(), size_t(1));
1801  SQLTypeInfo ti;
1802  return translateUnaryGeoConstructor(rex_function, ti, false);
1803  }
1804  if (func_resolve(rex_function->getName(),
1805  "convert_meters_to_pixel_width"sv,
1806  "convert_meters_to_pixel_height"sv,
1807  "is_point_in_view"sv,
1808  "is_point_size_in_view"sv)) {
1809  return translateFunctionWithGeoArg(rex_function);
1810  }
1811  if (func_resolve(rex_function->getName(),
1812  "ST_Distance"sv,
1813  "ST_MaxDistance"sv,
1814  "ST_Intersects"sv,
1815  "ST_Disjoint"sv,
1816  "ST_Contains"sv,
1817  "ST_Overlaps"sv,
1818  "ST_Approx_Overlaps"sv,
1819  "ST_Within"sv)) {
1820  CHECK_EQ(rex_function->size(), size_t(2));
1821  return translateBinaryGeoFunction(rex_function);
1822  }
1823  if (func_resolve(rex_function->getName(), "ST_DWithin"sv, "ST_DFullyWithin"sv)) {
1824  CHECK_EQ(rex_function->size(), size_t(3));
1825  return translateTernaryGeoFunction(rex_function);
1826  }
1827  if (rex_function->getName() == "OFFSET_IN_FRAGMENT"sv) {
1828  CHECK_EQ(size_t(0), rex_function->size());
1829  return translateOffsetInFragment();
1830  }
1831  if (rex_function->getName() == "ARRAY"sv) {
1832  // Var args; currently no check. Possible fix-me -- can array have 0 elements?
1833  return translateArrayFunction(rex_function);
1834  }
1835  if (func_resolve(rex_function->getName(),
1836  "ST_GeomFromText"sv,
1837  "ST_GeogFromText"sv,
1838  "ST_Centroid"sv,
1839  "ST_SetSRID"sv,
1840  "ST_Point"sv, // TODO: where should this and below live?
1841  "ST_PointN"sv,
1842  "ST_StartPoint"sv,
1843  "ST_EndPoint"sv,
1844  "ST_Transform"sv)) {
1845  SQLTypeInfo ti;
1846  return translateGeoProjection(rex_function, ti, false);
1847  }
1848  if (func_resolve(rex_function->getName(),
1849  "ST_Intersection"sv,
1850  "ST_Difference"sv,
1851  "ST_Union"sv,
1852  "ST_Buffer"sv,
1853  "ST_ConcaveHull"sv)) {
1854  CHECK_EQ(rex_function->size(), size_t(2));
1855  SQLTypeInfo ti;
1856  return translateBinaryGeoConstructor(rex_function, ti, false);
1857  }
1858  if (func_resolve(rex_function->getName(), "ST_IsEmpty"sv, "ST_IsValid"sv)) {
1859  CHECK_EQ(rex_function->size(), size_t(1));
1860  SQLTypeInfo ti;
1861  return translateUnaryGeoPredicate(rex_function, ti, false);
1862  }
1863  if (func_resolve(rex_function->getName(), "ST_Equals"sv)) {
1864  CHECK_EQ(rex_function->size(), size_t(2));
1865  // Attempt to generate a distance based check for points
1866  if (auto distance_check = translateBinaryGeoFunction(rex_function)) {
1867  return distance_check;
1868  }
1869  SQLTypeInfo ti;
1870  return translateBinaryGeoPredicate(rex_function, ti, false);
1871  }
1872 
1873  auto arg_expr_list = translateFunctionArgs(rex_function);
1874  if (rex_function->getName() == std::string("||") ||
1875  rex_function->getName() == std::string("SUBSTRING")) {
1876  SQLTypeInfo ret_ti(kTEXT, false);
1877  return makeExpr<Analyzer::FunctionOper>(
1878  ret_ti, rex_function->getName(), arg_expr_list);
1879  }
1880 
1881  // Reset possibly wrong return type of rex_function to the return
1882  // type of the optimal valid implementation. The return type can be
1883  // wrong in the case of multiple implementations of UDF functions
1884  // that have different return types but Calcite specifies the return
1885  // type according to the first implementation.
1886  SQLTypeInfo ret_ti;
1887  try {
1888  auto ext_func_sig = bind_function(rex_function->getName(), arg_expr_list);
1889  auto ext_func_args = ext_func_sig.getInputArgs();
1890  CHECK_LE(arg_expr_list.size(), ext_func_args.size());
1891  for (size_t i = 0, di = 0; i < arg_expr_list.size(); i++) {
1892  CHECK_LT(i + di, ext_func_args.size());
1893  auto ext_func_arg = ext_func_args[i + di];
1894  if (ext_func_arg == ExtArgumentType::PInt8 ||
1895  ext_func_arg == ExtArgumentType::PInt16 ||
1896  ext_func_arg == ExtArgumentType::PInt32 ||
1897  ext_func_arg == ExtArgumentType::PInt64 ||
1898  ext_func_arg == ExtArgumentType::PFloat ||
1899  ext_func_arg == ExtArgumentType::PDouble ||
1900  ext_func_arg == ExtArgumentType::PBool) {
1901  di++;
1902  // pointer argument follows length argument:
1903  CHECK(ext_func_args[i + di] == ExtArgumentType::Int64);
1904  }
1905  // fold casts on constants
1906  if (auto constant =
1907  std::dynamic_pointer_cast<Analyzer::Constant>(arg_expr_list[i])) {
1908  auto ext_func_arg_ti = ext_arg_type_to_type_info(ext_func_arg);
1909  if (ext_func_arg_ti != arg_expr_list[i]->get_type_info()) {
1910  arg_expr_list[i] = constant->add_cast(ext_func_arg_ti);
1911  }
1912  }
1913  }
1914 
1915  ret_ti = ext_arg_type_to_type_info(ext_func_sig.getRet());
1916  } catch (ExtensionFunctionBindingError& e) {
1917  LOG(WARNING) << "RelAlgTranslator::translateFunction: " << e.what();
1918  throw;
1919  }
1920 
1921  // By default, the extension function type will not allow nulls. If one of the arguments
1922  // is nullable, the extension function must also explicitly allow nulls.
1923  bool arguments_not_null = true;
1924  for (const auto& arg_expr : arg_expr_list) {
1925  if (!arg_expr->get_type_info().get_notnull()) {
1926  arguments_not_null = false;
1927  break;
1928  }
1929  }
1930  ret_ti.set_notnull(arguments_not_null);
1931 
1932  return makeExpr<Analyzer::FunctionOper>(ret_ti, rex_function->getName(), arg_expr_list);
1933 }
1934 
1935 namespace {
1936 
1937 std::vector<Analyzer::OrderEntry> translate_collation(
1938  const std::vector<SortField>& sort_fields) {
1939  std::vector<Analyzer::OrderEntry> collation;
1940  for (size_t i = 0; i < sort_fields.size(); ++i) {
1941  const auto& sort_field = sort_fields[i];
1942  collation.emplace_back(i,
1943  sort_field.getSortDir() == SortDirection::Descending,
1944  sort_field.getNullsPosition() == NullSortedPosition::First);
1945  }
1946  return collation;
1947 }
1948 
1949 size_t determineTimeValMultiplierForTimeType(const SQLTypes& window_frame_bound_type,
1950  const Analyzer::Constant* const_expr) {
1951  const auto time_unit_val = const_expr->get_constval().bigintval;
1952  if (window_frame_bound_type == kINTERVAL_DAY_TIME) {
1953  if (time_unit_val == kMilliSecsPerSec) {
1954  return 1;
1955  } else if (time_unit_val == kMilliSecsPerMin) {
1956  return kSecsPerMin;
1957  } else if (time_unit_val == kMilliSecsPerHour) {
1958  return kSecsPerHour;
1959  }
1960  }
1961  CHECK(false);
1962  return kUNKNOWN_FIELD;
1963 }
1964 
1965 ExtractField determineTimeUnit(const SQLTypes& window_frame_bound_type,
1966  const Analyzer::Constant* const_expr) {
1967  const auto time_unit_val = const_expr->get_constval().bigintval;
1968  if (window_frame_bound_type == kINTERVAL_DAY_TIME) {
1969  if (time_unit_val == kMilliSecsPerSec) {
1970  return kSECOND;
1971  } else if (time_unit_val == kMilliSecsPerMin) {
1972  return kMINUTE;
1973  } else if (time_unit_val == kMilliSecsPerHour) {
1974  return kHOUR;
1975  } else if (time_unit_val == kMilliSecsPerDay) {
1976  return kDAY;
1977  }
1978  } else {
1979  CHECK(window_frame_bound_type == kINTERVAL_YEAR_MONTH);
1980  if (time_unit_val == 1) {
1981  return kMONTH;
1982  } else if (time_unit_val == 12) {
1983  return kYEAR;
1984  }
1985  }
1986  CHECK(false);
1987  return kUNKNOWN_FIELD;
1988 }
1989 } // namespace
1990 
1991 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateWindowFunction(
1992  const RexWindowFunctionOperator* rex_window_function) const {
1993  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1994  for (size_t i = 0; i < rex_window_function->size(); ++i) {
1995  args.push_back(translateScalarRex(rex_window_function->getOperand(i)));
1996  }
1997  std::vector<std::shared_ptr<Analyzer::Expr>> partition_keys;
1998  for (const auto& partition_key : rex_window_function->getPartitionKeys()) {
1999  partition_keys.push_back(translateScalarRex(partition_key.get()));
2000  }
2001  std::vector<std::shared_ptr<Analyzer::Expr>> order_keys;
2002  for (const auto& order_key : rex_window_function->getOrderKeys()) {
2003  order_keys.push_back(translateScalarRex(order_key.get()));
2004  }
2005  auto ti = rex_window_function->getType();
2006  auto window_func_kind = rex_window_function->getKind();
2007  if (window_function_is_value(window_func_kind)) {
2008  CHECK_GE(args.size(), 1u);
2009  ti = args.front()->get_type_info();
2010  }
2011  auto determine_frame_bound_type =
2013  if (bound.unbounded) {
2014  CHECK(!bound.bound_expr && !bound.is_current_row);
2015  if (bound.following) {
2017  } else if (bound.preceding) {
2019  }
2020  } else {
2021  if (bound.is_current_row) {
2022  CHECK(!bound.unbounded && !bound.bound_expr);
2024  } else {
2025  CHECK(!bound.unbounded && bound.bound_expr);
2026  if (bound.following) {
2028  } else if (bound.preceding) {
2030  }
2031  }
2032  }
2034  };
2035  auto is_negative_framing_bound =
2036  [](const SQLTypes t, const Datum& d, bool is_time_unit = false) {
2037  switch (t) {
2038  case kTINYINT:
2039  return d.tinyintval < 0;
2040  case kSMALLINT:
2041  return d.smallintval < 0;
2042  case kINT:
2043  return d.intval < 0;
2044  case kDOUBLE: {
2045  // the only case that double type is used is for handling time interval
2046  // i.e., represent tiny time units like nanosecond and microsecond as the
2047  // equivalent time value with SECOND time unit
2048  CHECK(is_time_unit);
2049  return d.doubleval < 0;
2050  }
2051  case kDECIMAL:
2052  case kNUMERIC:
2053  case kBIGINT:
2054  return d.bigintval < 0;
2055  default: {
2056  throw std::runtime_error(
2057  "We currently only support integer-type literal expression as a window "
2058  "frame bound expression");
2059  }
2060  }
2061  };
2062 
2063  bool negative_constant = false;
2064  bool detect_invalid_frame_start_bound_expr = false;
2065  bool detect_invalid_frame_end_bound_expr = false;
2066  auto& frame_start_bound = rex_window_function->getFrameStartBound();
2067  auto& frame_end_bound = rex_window_function->getFrameEndBound();
2068  bool has_end_bound_frame_expr = false;
2069  std::shared_ptr<Analyzer::Expr> frame_start_bound_expr;
2070  SqlWindowFrameBoundType frame_start_bound_type =
2071  determine_frame_bound_type(frame_start_bound);
2072  std::shared_ptr<Analyzer::Expr> frame_end_bound_expr;
2073  SqlWindowFrameBoundType frame_end_bound_type =
2074  determine_frame_bound_type(frame_end_bound);
2075  bool has_framing_clause =
2077  auto frame_mode = rex_window_function->isRows()
2080  if (order_keys.empty()) {
2081  if (frame_start_bound_type == SqlWindowFrameBoundType::UNBOUNDED_PRECEDING &&
2082  frame_end_bound_type == SqlWindowFrameBoundType::UNBOUNDED_FOLLOWING) {
2083  // Calcite sets UNBOUNDED PRECEDING ~ UNBOUNDED_FOLLOWING as its default frame bound
2084  // if the window context has no order by clause regardless of the existence of
2085  // user-given window frame bound but at this point we have no way to recognize the
2086  // absence of the frame definition of this window context
2087  has_framing_clause = false;
2088  }
2089  } else {
2090  if (frame_start_bound_type == SqlWindowFrameBoundType::UNBOUNDED_PRECEDING &&
2091  frame_end_bound_type == SqlWindowFrameBoundType::CURRENT_ROW) {
2092  // Calcite sets this frame bound by default when order by clause is given but has no
2093  // window frame definition (even if user gives the same bound, our previous window
2094  // computation logic returns exactly the same result)
2095  has_framing_clause = false;
2096  }
2097  auto translate_frame_bound_expr = [&](const RexScalar* bound_expr) {
2098  std::shared_ptr<Analyzer::Expr> translated_expr;
2099  const auto rex_oper = dynamic_cast<const RexOperator*>(bound_expr);
2100  if (rex_oper && rex_oper->getType().is_timeinterval()) {
2101  translated_expr = translateScalarRex(rex_oper);
2102  const auto bin_oper =
2103  dynamic_cast<const Analyzer::BinOper*>(translated_expr.get());
2104  auto time_literal_expr =
2105  dynamic_cast<const Analyzer::Constant*>(bin_oper->get_left_operand());
2106  CHECK(time_literal_expr);
2107  negative_constant =
2108  is_negative_framing_bound(time_literal_expr->get_type_info().get_type(),
2109  time_literal_expr->get_constval(),
2110  true);
2111  return std::make_pair(false, translated_expr);
2112  }
2113  if (dynamic_cast<const RexLiteral*>(bound_expr)) {
2114  translated_expr = translateScalarRex(bound_expr);
2115  if (auto literal_expr =
2116  dynamic_cast<const Analyzer::Constant*>(translated_expr.get())) {
2117  negative_constant = is_negative_framing_bound(
2118  literal_expr->get_type_info().get_type(), literal_expr->get_constval());
2119  return std::make_pair(false, translated_expr);
2120  }
2121  }
2122  return std::make_pair(true, translated_expr);
2123  };
2124 
2125  if (frame_start_bound.bound_expr) {
2126  std::tie(detect_invalid_frame_start_bound_expr, frame_start_bound_expr) =
2127  translate_frame_bound_expr(frame_start_bound.bound_expr.get());
2128  }
2129 
2130  if (frame_end_bound.bound_expr) {
2131  std::tie(detect_invalid_frame_end_bound_expr, frame_end_bound_expr) =
2132  translate_frame_bound_expr(frame_end_bound.bound_expr.get());
2133  }
2134 
2135  // currently we only support literal expression as frame bound expression
2136  if (detect_invalid_frame_start_bound_expr || detect_invalid_frame_end_bound_expr) {
2137  throw std::runtime_error(
2138  "We currently only support literal expression as a window frame bound "
2139  "expression");
2140  }
2141 
2142  // note that Calcite already has frame-bound constraint checking logic, but we
2143  // also check various invalid cases for safety
2144  if (negative_constant) {
2145  throw std::runtime_error(
2146  "A constant expression for window framing should have nonnegative value.");
2147  }
2148 
2149  auto handle_time_interval_expr_if_necessary = [&](const Analyzer::Expr* bound_expr,
2150  SqlWindowFrameBoundType bound_type,
2151  bool for_start_bound) {
2152  if (bound_expr && bound_expr->get_type_info().is_timeinterval()) {
2153  const auto bound_bin_oper = dynamic_cast<const Analyzer::BinOper*>(bound_expr);
2154  CHECK(bound_bin_oper->get_optype() == kMULTIPLY);
2155  auto translated_expr = translateIntervalExprForWindowFraming(
2156  order_keys.front(),
2158  bound_bin_oper);
2159  if (for_start_bound) {
2160  frame_start_bound_expr = translated_expr;
2161  } else {
2162  frame_end_bound_expr = translated_expr;
2163  }
2164  }
2165  };
2166  handle_time_interval_expr_if_necessary(
2167  frame_start_bound_expr.get(), frame_start_bound_type, true);
2168  handle_time_interval_expr_if_necessary(
2169  frame_end_bound_expr.get(), frame_end_bound_type, false);
2170  }
2171 
2172  if (frame_start_bound.following) {
2173  if (frame_end_bound.is_current_row) {
2174  throw std::runtime_error(
2175  "Window framing starting from following row cannot end with current row.");
2176  } else if (has_end_bound_frame_expr && frame_end_bound.preceding) {
2177  throw std::runtime_error(
2178  "Window framing starting from following row cannot have preceding rows.");
2179  }
2180  }
2181  if (frame_start_bound.is_current_row && frame_end_bound.preceding &&
2182  !frame_end_bound.unbounded && has_end_bound_frame_expr) {
2183  throw std::runtime_error(
2184  "Window framing starting from current row cannot have preceding rows.");
2185  }
2186  if (has_framing_clause) {
2188  if (order_keys.size() != 1) {
2189  throw std::runtime_error(
2190  "Window framing with range mode requires a single order-by column");
2191  }
2192  if (!frame_start_bound_expr &&
2193  frame_start_bound_type == SqlWindowFrameBoundType::UNBOUNDED_PRECEDING &&
2194  !frame_end_bound_expr &&
2195  frame_end_bound_type == SqlWindowFrameBoundType::CURRENT_ROW) {
2196  has_framing_clause = false;
2197  VLOG(1) << "Ignore range framing mode with a frame bound between "
2198  "UNBOUNDED_PRECEDING and CURRENT_ROW";
2199  }
2200  std::set<const Analyzer::ColumnVar*,
2201  bool (*)(const Analyzer::ColumnVar*, const Analyzer::ColumnVar*)>
2203  order_keys.front()->collect_column_var(colvar_set, false);
2204  for (auto cv : colvar_set) {
2205  if (!(cv->get_type_info().is_integer() || cv->get_type_info().is_fp() ||
2206  cv->get_type_info().is_time())) {
2207  has_framing_clause = false;
2208  VLOG(1) << "Range framing mode with non-number type ordering column is not "
2209  "supported yet, skip window framing";
2210  }
2211  }
2212  }
2213  }
2214  switch (window_func_kind) {
2217  CHECK(has_framing_clause);
2218  const auto num_args = args.size();
2219  const auto func_name = ::toString(window_func_kind);
2220  if (num_args == 1) {
2221  Datum d;
2222  d.intval = 1;
2223  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, d));
2224  } else if (num_args < 1 || num_args > 2) {
2225  throw std::runtime_error(func_name + " has an invalid number of input arguments");
2226  }
2227  const auto target_expr_cv =
2228  dynamic_cast<const Analyzer::ColumnVar*>(args.front().get());
2229  if (!target_expr_cv) {
2230  throw std::runtime_error("Currently, " + func_name +
2231  " only allows a column reference as its first argument");
2232  }
2233  const auto target_ti = target_expr_cv->get_type_info();
2234  if (target_ti.is_dict_encoded_string()) {
2235  // Calcite does not represent a window function having dictionary encoded text
2236  // type as its output properly, so we need to set its output type manually
2237  ti.set_compression(kENCODING_DICT);
2238  ti.set_comp_param(target_expr_cv->get_comp_param());
2239  ti.set_fixed_size();
2240  }
2241  const auto target_offset_cv =
2242  dynamic_cast<const Analyzer::Constant*>(args[1].get());
2243  if (!target_expr_cv ||
2244  is_negative_framing_bound(target_offset_cv->get_type_info().get_type(),
2245  target_offset_cv->get_constval())) {
2246  throw std::runtime_error(
2247  "Currently, " + func_name +
2248  " only allows non-negative constant as its second argument");
2249  }
2250  break;
2251  }
2252  default:
2253  break;
2254  }
2255  if (!has_framing_clause) {
2256  frame_start_bound_type = SqlWindowFrameBoundType::UNKNOWN;
2257  frame_end_bound_type = SqlWindowFrameBoundType::UNKNOWN;
2258  frame_start_bound_expr = nullptr;
2259  frame_end_bound_expr = nullptr;
2260  }
2261  return makeExpr<Analyzer::WindowFunction>(
2262  ti,
2263  rex_window_function->getKind(),
2264  args,
2265  partition_keys,
2266  order_keys,
2267  has_framing_clause ? frame_mode : Analyzer::WindowFunction::FrameBoundType::NONE,
2268  makeExpr<Analyzer::WindowFrame>(frame_start_bound_type, frame_start_bound_expr),
2269  makeExpr<Analyzer::WindowFrame>(frame_end_bound_type, frame_end_bound_expr),
2270  translate_collation(rex_window_function->getCollation()));
2271 }
2272 
2274  std::shared_ptr<Analyzer::Expr> order_key,
2275  bool for_preceding_bound,
2276  const Analyzer::BinOper* frame_bound_expr) const {
2277  // translate time interval expression and prepare appropriate frame bound expression:
2278  // a) manually compute time unit datum: time type
2279  // b) use dateadd expression: date and timestamp
2280  const auto order_key_ti = order_key->get_type_info();
2281  const auto frame_bound_ti = frame_bound_expr->get_type_info();
2282  const auto time_val_expr =
2283  dynamic_cast<const Analyzer::Constant*>(frame_bound_expr->get_left_operand());
2284  const auto time_unit_val_expr =
2285  dynamic_cast<const Analyzer::Constant*>(frame_bound_expr->get_right_operand());
2286  ExtractField time_unit =
2287  determineTimeUnit(frame_bound_ti.get_type(), time_unit_val_expr);
2288  bool invalid_time_unit_type = false;
2289  bool invalid_frame_bound_expr_type = false;
2290  Datum d;
2291  auto prepare_time_value_datum = [&d,
2292  &invalid_frame_bound_expr_type,
2293  &time_val_expr,
2294  &for_preceding_bound](bool is_timestamp_second) {
2295  // currently, Calcite only accepts interval with second, so to represent
2296  // smaller time units like millisecond, we have to use decimal point like
2297  // INTERVAL 0.003 SECOND (for millisecond)
2298  // thus, depending on what time unit we want to represent, Calcite analyzes
2299  // the time value to one of following two types: integer and decimal (and
2300  // numeric) types
2301  switch (time_val_expr->get_type_info().get_type()) {
2302  case kTINYINT: {
2303  d.bigintval = time_val_expr->get_constval().tinyintval;
2304  break;
2305  }
2306  case kSMALLINT: {
2307  d.bigintval = time_val_expr->get_constval().smallintval;
2308  break;
2309  }
2310  case kINT: {
2311  d.bigintval = time_val_expr->get_constval().intval;
2312  break;
2313  }
2314  case kBIGINT: {
2315  d.bigintval = time_val_expr->get_constval().bigintval;
2316  break;
2317  }
2318  case kDECIMAL:
2319  case kNUMERIC: {
2320  if (!is_timestamp_second) {
2321  // date and time type only use integer type as their time value
2322  invalid_frame_bound_expr_type = true;
2323  break;
2324  }
2325  d.bigintval = time_val_expr->get_constval().bigintval;
2326  break;
2327  }
2328  case kDOUBLE: {
2329  if (!is_timestamp_second) {
2330  // date and time type only use integer type as their time value
2331  invalid_frame_bound_expr_type = true;
2332  break;
2333  }
2334  d.bigintval = time_val_expr->get_constval().doubleval *
2335  pow(10, time_val_expr->get_type_info().get_scale());
2336  break;
2337  }
2338  default: {
2339  invalid_frame_bound_expr_type = true;
2340  break;
2341  }
2342  }
2343  if (for_preceding_bound) {
2344  d.bigintval *= -1;
2345  }
2346  };
2347 
2348  switch (order_key_ti.get_type()) {
2349  case kTIME: {
2350  if (time_val_expr->get_type_info().is_integer()) {
2351  if (time_unit == kSECOND || time_unit == kMINUTE || time_unit == kHOUR) {
2352  const auto time_multiplier = determineTimeValMultiplierForTimeType(
2353  frame_bound_ti.get_type(), time_unit_val_expr);
2354  switch (time_val_expr->get_type_info().get_type()) {
2355  case kTINYINT: {
2356  d.bigintval = time_val_expr->get_constval().tinyintval * time_multiplier;
2357  break;
2358  }
2359  case kSMALLINT: {
2360  d.bigintval = time_val_expr->get_constval().smallintval * time_multiplier;
2361  break;
2362  }
2363  case kINT: {
2364  d.bigintval = time_val_expr->get_constval().intval * time_multiplier;
2365  break;
2366  }
2367  case kBIGINT: {
2368  d.bigintval = time_val_expr->get_constval().bigintval * time_multiplier;
2369  break;
2370  }
2371  default: {
2372  UNREACHABLE();
2373  break;
2374  }
2375  }
2376  } else {
2377  invalid_frame_bound_expr_type = true;
2378  }
2379  } else {
2380  invalid_time_unit_type = true;
2381  }
2382  if (invalid_frame_bound_expr_type) {
2383  throw std::runtime_error(
2384  "Invalid time unit is used to define window frame bound expression for " +
2385  order_key_ti.get_type_name() + " type");
2386  } else if (invalid_time_unit_type) {
2387  throw std::runtime_error(
2388  "Window frame bound expression has an invalid type for " +
2389  order_key_ti.get_type_name() + " type");
2390  }
2391  return std::make_shared<Analyzer::Constant>(kBIGINT, false, d);
2392  }
2393  case kDATE: {
2394  DateaddField daField;
2395  if (time_val_expr->get_type_info().is_integer()) {
2396  switch (time_unit) {
2397  case kDAY: {
2398  daField = to_dateadd_field("day");
2399  break;
2400  }
2401  case kMONTH: {
2402  daField = to_dateadd_field("month");
2403  break;
2404  }
2405  case kYEAR: {
2406  daField = to_dateadd_field("year");
2407  break;
2408  }
2409  default: {
2410  invalid_frame_bound_expr_type = true;
2411  break;
2412  }
2413  }
2414  } else {
2415  invalid_time_unit_type = true;
2416  }
2417  if (invalid_frame_bound_expr_type) {
2418  throw std::runtime_error(
2419  "Invalid time unit is used to define window frame bound expression for " +
2420  order_key_ti.get_type_name() + " type");
2421  } else if (invalid_time_unit_type) {
2422  throw std::runtime_error(
2423  "Window frame bound expression has an invalid type for " +
2424  order_key_ti.get_type_name() + " type");
2425  }
2426  prepare_time_value_datum(false);
2427  const auto cast_number_units = makeExpr<Analyzer::Constant>(kBIGINT, false, d);
2428  const int dim = order_key_ti.get_dimension();
2429  return makeExpr<Analyzer::DateaddExpr>(
2430  SQLTypeInfo(kTIMESTAMP, dim, 0, false), daField, cast_number_units, order_key);
2431  }
2432  case kTIMESTAMP: {
2433  DateaddField daField;
2434  switch (time_unit) {
2435  case kSECOND: {
2436  // classify
2437  switch (time_val_expr->get_type_info().get_scale()) {
2438  case 0: {
2439  daField = to_dateadd_field("second");
2440  break;
2441  }
2442  case 3: {
2443  daField = to_dateadd_field("millisecond");
2444  break;
2445  }
2446  case 6: {
2447  daField = to_dateadd_field("microsecond");
2448  break;
2449  }
2450  case 9: {
2451  daField = to_dateadd_field("nanosecond");
2452  break;
2453  }
2454  default:
2455  UNREACHABLE();
2456  break;
2457  }
2458  prepare_time_value_datum(true);
2459  break;
2460  }
2461  case kMINUTE: {
2462  daField = to_dateadd_field("minute");
2463  prepare_time_value_datum(false);
2464  break;
2465  }
2466  case kHOUR: {
2467  daField = to_dateadd_field("hour");
2468  prepare_time_value_datum(false);
2469  break;
2470  }
2471  case kDAY: {
2472  daField = to_dateadd_field("day");
2473  prepare_time_value_datum(false);
2474  break;
2475  }
2476  case kMONTH: {
2477  daField = to_dateadd_field("month");
2478  prepare_time_value_datum(false);
2479  break;
2480  }
2481  case kYEAR: {
2482  daField = to_dateadd_field("year");
2483  prepare_time_value_datum(false);
2484  break;
2485  }
2486  default: {
2487  invalid_time_unit_type = true;
2488  break;
2489  }
2490  }
2491  if (!invalid_time_unit_type) {
2492  const auto cast_number_units = makeExpr<Analyzer::Constant>(kBIGINT, false, d);
2493  const int dim = order_key_ti.get_dimension();
2494  return makeExpr<Analyzer::DateaddExpr>(SQLTypeInfo(kTIMESTAMP, dim, 0, false),
2495  daField,
2496  cast_number_units,
2497  order_key);
2498  }
2499  return nullptr;
2500  }
2501  default: {
2502  UNREACHABLE();
2503  break;
2504  }
2505  }
2506  if (invalid_frame_bound_expr_type) {
2507  throw std::runtime_error(
2508  "Invalid time unit is used to define window frame bound expression for " +
2509  order_key_ti.get_type_name() + " type");
2510  } else if (invalid_time_unit_type) {
2511  throw std::runtime_error("Window frame bound expression has an invalid type for " +
2512  order_key_ti.get_type_name() + " type");
2513  }
2514  return nullptr;
2515 }
2516 
2518  const RexFunctionOperator* rex_function) const {
2519  std::vector<std::shared_ptr<Analyzer::Expr>> args;
2520  for (size_t i = 0; i < rex_function->size(); ++i) {
2521  args.push_back(translateScalarRex(rex_function->getOperand(i)));
2522  }
2523  return args;
2524 }
2525 
2527  const std::shared_ptr<Analyzer::Expr> qual_expr) {
2528  CHECK(qual_expr);
2529  auto bin_oper = std::dynamic_pointer_cast<const Analyzer::BinOper>(qual_expr);
2530  if (!bin_oper) {
2531  const auto rewritten_qual_expr = rewrite_expr(qual_expr.get());
2532  return {{}, {rewritten_qual_expr ? rewritten_qual_expr : qual_expr}};
2533  }
2534 
2535  if (bin_oper->get_optype() == kAND) {
2536  const auto lhs_cf = qual_to_conjunctive_form(bin_oper->get_own_left_operand());
2537  const auto rhs_cf = qual_to_conjunctive_form(bin_oper->get_own_right_operand());
2538  auto simple_quals = lhs_cf.simple_quals;
2539  simple_quals.insert(
2540  simple_quals.end(), rhs_cf.simple_quals.begin(), rhs_cf.simple_quals.end());
2541  auto quals = lhs_cf.quals;
2542  quals.insert(quals.end(), rhs_cf.quals.begin(), rhs_cf.quals.end());
2543  return {simple_quals, quals};
2544  }
2545  int rte_idx{0};
2546  const auto simple_qual = bin_oper->normalize_simple_predicate(rte_idx);
2547  return simple_qual ? QualsConjunctiveForm{{simple_qual}, {}}
2548  : QualsConjunctiveForm{{}, {qual_expr}};
2549 }
2550 
2551 std::vector<std::shared_ptr<Analyzer::Expr>> qual_to_disjunctive_form(
2552  const std::shared_ptr<Analyzer::Expr>& qual_expr) {
2553  CHECK(qual_expr);
2554  const auto bin_oper = std::dynamic_pointer_cast<const Analyzer::BinOper>(qual_expr);
2555  if (!bin_oper) {
2556  const auto rewritten_qual_expr = rewrite_expr(qual_expr.get());
2557  return {rewritten_qual_expr ? rewritten_qual_expr : qual_expr};
2558  }
2559  if (bin_oper->get_optype() == kOR) {
2560  const auto lhs_df = qual_to_disjunctive_form(bin_oper->get_own_left_operand());
2561  const auto rhs_df = qual_to_disjunctive_form(bin_oper->get_own_right_operand());
2562  auto quals = lhs_df;
2563  quals.insert(quals.end(), rhs_df.begin(), rhs_df.end());
2564  return quals;
2565  }
2566  return {qual_expr};
2567 }
2568 
2569 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateHPTLiteral(
2570  const RexFunctionOperator* rex_function) const {
2571  /* since calcite uses Avatica package called DateTimeUtils to parse timestamp strings.
2572  Therefore any string having fractional seconds more 3 places after the decimal
2573  (milliseconds) will get truncated to 3 decimal places, therefore we lose precision
2574  (us|ns). Issue: [BE-2461] Here we are hijacking literal cast to Timestamp(6|9) from
2575  calcite and translating them to generate our own casts.
2576  */
2577  CHECK_EQ(size_t(1), rex_function->size());
2578  const auto operand = translateScalarRex(rex_function->getOperand(0));
2579  const auto& operand_ti = operand->get_type_info();
2580  const auto& target_ti = rex_function->getType();
2581  if (!operand_ti.is_string()) {
2582  throw std::runtime_error(
2583  "High precision timestamp cast argument must be a string. Input type is: " +
2584  operand_ti.get_type_name());
2585  } else if (!target_ti.is_high_precision_timestamp()) {
2586  throw std::runtime_error(
2587  "Cast target type should be high precision timestamp. Input type is: " +
2588  target_ti.get_type_name());
2589  } else if (target_ti.get_dimension() != 6 && target_ti.get_dimension() != 9) {
2590  throw std::runtime_error(
2591  "Cast target type should be TIMESTAMP(6|9). Input type is: TIMESTAMP(" +
2592  std::to_string(target_ti.get_dimension()) + ")");
2593  } else {
2594  return operand->add_cast(target_ti);
2595  }
2596 }
DEVICE auto upper_bound(ARGS &&...args)
Definition: gpu_enabled.h:123
Defines data structures for the semantic analysis phase of query processing.
Definition: sqldefs.h:70
SqlWindowFrameBoundType
Definition: sqldefs.h:141
const RexScalar * getThen(const size_t idx) const
Definition: RelAlgDag.h:400
const std::vector< JoinType > join_types_
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:405
void set_compression(EncodingType c)
Definition: sqltypes.h:525
SQLAgg
Definition: sqldefs.h:72
static std::shared_ptr< Analyzer::Expr > normalize(const std::list< std::pair< std::shared_ptr< Analyzer::Expr >, std::shared_ptr< Analyzer::Expr >>> &, const std::shared_ptr< Analyzer::Expr >, const Executor *executor=nullptr)
#define CHECK_EQ(x, y)
Definition: Logger.h:230
auto func_resolve
std::shared_ptr< Analyzer::Expr > translateOffsetInFragment() const
SqlStringOpKind name_to_string_op_kind(const std::string &func_name)
Definition: sqldefs.h:275
static std::shared_ptr< Analyzer::Expr > get(const std::string &)
Definition: ParserNode.cpp:236
std::shared_ptr< Analyzer::Expr > translateCurrentTimestamp() const
std::shared_ptr< Analyzer::Expr > translateBinaryGeoPredicate(const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
SQLAgg getKind() const
Definition: RelAlgDag.h:749
Definition: sqltypes.h:63
std::shared_ptr< Analyzer::Expr > translateRegexp(const RexFunctionOperator *) const
static bool colvar_comp(const ColumnVar *l, const ColumnVar *r)
Definition: Analyzer.h:216
SQLTypes
Definition: sqltypes.h:52
static constexpr int64_t kSecsPerHour
size_t getOperand(size_t idx) const
Definition: RelAlgDag.h:755
const Executor * executor_
std::shared_ptr< Analyzer::Expr > translateUnlikely(const RexFunctionOperator *) const
const RexScalar * getElse() const
Definition: RelAlgDag.h:405
void collect_column_var(std::set< const ColumnVar *, bool(*)(const ColumnVar *, const ColumnVar *)> &colvar_set, bool include_agg) const override
Definition: Analyzer.h:221
static constexpr int64_t kSecsPerMin
std::shared_ptr< Analyzer::Expr >(RelAlgTranslator::*)(RexScalar const *) const Handler
SQLQualifier
Definition: sqldefs.h:70
static std::shared_ptr< Analyzer::Expr > analyzeValue(const int64_t intval)
Definition: ParserNode.cpp:161
std::shared_ptr< Analyzer::Expr > translateFunction(const RexFunctionOperator *) const
SQLTypeInfo get_nullable_logical_type_info(const SQLTypeInfo &type_info)
Definition: sqltypes.h:1242
#define LOG(tag)
Definition: Logger.h:216
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const SQLTypeInfo & getType() const
Definition: RelAlgDag.h:259
size_t size() const
Definition: RelAlgDag.h:245
static constexpr int64_t kMilliSecsPerDay
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:247
std::shared_ptr< Analyzer::Expr > translateUoper(const RexOperator *) const
HOST DEVICE int get_scale() const
Definition: sqltypes.h:409
const Expr * get_right_operand() const
Definition: Analyzer.h:451
const std::vector< SortField > & getCollation() const
Definition: RelAlgDag.h:600
SQLOps
Definition: sqldefs.h:28
std::shared_ptr< Analyzer::Expr > translateDateadd(const RexFunctionOperator *) const
int8_t boolval
Definition: sqltypes.h:231
static bool isFramingAvailableWindowFunc(SqlWindowFunctionKind kind)
Definition: Analyzer.h:2447
static std::shared_ptr< Analyzer::Expr > normalize(const SQLOps optype, const SQLQualifier qual, std::shared_ptr< Analyzer::Expr > left_expr, std::shared_ptr< Analyzer::Expr > right_expr, const Executor *executor=nullptr)
Definition: ParserNode.cpp:370
Definition: sqldefs.h:37
#define UNREACHABLE()
Definition: Logger.h:266
std::shared_ptr< Analyzer::Expr > translateIntervalExprForWindowFraming(std::shared_ptr< Analyzer::Expr > order_key, bool for_preceding_bound, const Analyzer::BinOper *frame_bound_expr) const
#define CHECK_GE(x, y)
Definition: Logger.h:235
std::shared_ptr< Analyzer::Expr > translateAbs(const RexFunctionOperator *) const
Definition: sqldefs.h:48
Definition: sqldefs.h:29
const RexScalar * getWhen(const size_t idx) const
Definition: RelAlgDag.h:395
std::shared_ptr< Analyzer::Expr > ExpressionPtr
Definition: Analyzer.h:187
std::string getString(int32_t string_id) const
std::shared_ptr< Analyzer::Expr > getInIntegerSetExpr(std::shared_ptr< Analyzer::Expr > arg, const ResultSet &val_set) const
Definition: sqldefs.h:40
SQLTypeInfo get_agg_type(const SQLAgg agg_kind, const Analyzer::Expr *arg_expr)
std::shared_ptr< Analyzer::Expr > translateItem(const RexFunctionOperator *) const
std::string toString(const QueryDescriptionType &type)
Definition: Types.h:64
std::shared_ptr< Analyzer::Constant > makeNumericConstant(const SQLTypeInfo &ti, const long val)
Analyzer::ExpressionPtr rewrite_expr(const Analyzer::Expr *expr)
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:404
bool operator()(IndexedHandler const &pair) const
QualsConjunctiveForm qual_to_conjunctive_form(const std::shared_ptr< Analyzer::Expr > qual_expr)
bool is_number() const
Definition: sqltypes.h:605
#define CHECK_GT(x, y)
Definition: Logger.h:234
bool is_agg_supported_for_type(const SQLAgg &agg_kind, const SQLTypeInfo &arg_ti)
std::shared_ptr< Analyzer::Expr > translateGeoProjection(const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
double inline_fp_null_val(const SQL_TYPE_INFO &ti)
int32_t intval
Definition: sqltypes.h:234
bool is_time() const
Definition: sqltypes.h:606
std::shared_ptr< Analyzer::Expr > translateOper(const RexOperator *) const
std::string to_string(char const *&&v)
std::shared_ptr< Analyzer::Expr > translateDatediff(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateInput(const RexInput *) const
std::shared_ptr< Analyzer::Expr > translateSign(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateUnaryGeoFunction(const RexFunctionOperator *) const
static constexpr int64_t kMilliSecsPerMin
bool g_enable_string_functions
std::shared_ptr< Analyzer::Expr > translateGeoOverlapsOper(const RexOperator *) const
Definition: sqldefs.h:74
static constexpr int64_t kMilliSecsPerSec
ExtractField to_datepart_field(const std::string &field)
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
robin_hood::unordered_map< RexScalar const *, std::shared_ptr< Analyzer::Expr > > cache_
unsigned getIndex() const
Definition: RelAlgDag.h:72
Supported runtime functions management and retrieval.
future< Result > async(Fn &&fn, Args &&...args)
static std::shared_ptr< Analyzer::Expr > translateLiteral(const RexLiteral *)
SQLOps getOperator() const
Definition: RelAlgDag.h:257
bool window_function_is_value(const SqlWindowFunctionKind kind)
Definition: WindowContext.h:29
static constexpr int32_t INVALID_STR_ID
CONSTEXPR DEVICE bool is_null(const T &value)
Classes representing a parse tree.
std::shared_ptr< Analyzer::Expr > translateDatetime(const RexFunctionOperator *) const
void set_fixed_size()
Definition: sqltypes.h:523
DateaddField
Definition: DateAdd.h:42
void fill_dictionary_encoded_in_vals(std::vector< int64_t > &in_vals, std::atomic< size_t > &total_in_vals_count, const ResultSet *values_rowset, const std::pair< int64_t, int64_t > values_rowset_slice, const StringDictionaryProxy *source_dict, const StringDictionaryProxy *dest_dict, const int64_t needle_null_val)
#define CHECK_NE(x, y)
Definition: Logger.h:231
const std::shared_ptr< Analyzer::Expr > generate() const
std::shared_ptr< Analyzer::Expr > translateStringOper(const RexFunctionOperator *) const
static std::shared_ptr< Analyzer::Expr > get(std::shared_ptr< Analyzer::Expr > arg_expr, std::shared_ptr< Analyzer::Expr > pattern_expr, std::shared_ptr< Analyzer::Expr > escape_expr, const bool is_not)
Definition: ParserNode.cpp:786
size_t determineTimeValMultiplierForTimeType(const SQLTypes &window_frame_bound_type, const Analyzer::Constant *const_expr)
void set_scale(int s)
Definition: sqltypes.h:519
int64_t bigintval
Definition: sqltypes.h:235
bool is_timeinterval() const
Definition: sqltypes.h:611
std::pair< std::shared_ptr< Analyzer::Expr >, SQLQualifier > getQuantifiedRhs(const RexScalar *) const
std::vector< Analyzer::OrderEntry > translate_collation(const std::vector< SortField > &sort_fields)
size_t branchCount() const
Definition: RelAlgDag.h:393
std::shared_ptr< Analyzer::Expr > translateCurrentTime() const
Definition: sqldefs.h:36
Definition: sqldefs.h:76
bool g_enable_watchdog
Definition: sqldefs.h:70
int getDatabaseId() const
Definition: Catalog.h:298
int16_t smallintval
Definition: sqltypes.h:233
SQLTypeInfo build_type_info(const SQLTypes sql_type, const int scale, const int precision)
DatetruncField to_datediff_field(const std::string &field)
void translate_string_ids(std::vector< int32_t > &dest_ids, const LeafHostInfo &dict_server_host, const DictRef dest_dict_ref, const std::vector< int32_t > &source_ids, const DictRef source_dict_ref, const int32_t dest_generation)
bool is_boolean() const
Definition: sqltypes.h:607
std::array< IndexedHandler, sizeof...(Ts)> makeHandlers()
const RexWindowBound & getFrameEndBound() const
Definition: RelAlgDag.h:604
std::shared_ptr< Analyzer::Expr > translate(const RexScalar *rex) const
const std::vector< LeafHostInfo > & getStringDictionaryHosts() const
Definition: Catalog.cpp:1996
std::tuple< T, std::vector< SQLTypeInfo > > bind_function(std::string name, Analyzer::ExpressionPtrVector func_args, const std::vector< T > &ext_funcs, const std::string processor)
const ColumnDescriptor * getMetadataForColumnBySpi(const int tableId, const size_t spi) const
Definition: Catalog.cpp:2057
Argument type based extension function binding.
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:82
const std::unordered_map< const RelAlgNode *, int > input_to_nest_level_
#define UNLIKELY(x)
Definition: likely.h:25
Definition: sqldefs.h:33
void set_comp_param(int p)
Definition: sqltypes.h:526
#define CHECK_LT(x, y)
Definition: Logger.h:232
Definition: sqltypes.h:66
Definition: sqltypes.h:67
Analyzer::ExpressionPtrVector translateFunctionArgs(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateUnaryGeoPredicate(const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
Definition: sqldefs.h:39
Definition: sqldefs.h:70
const ConstRexScalarPtrVector & getPartitionKeys() const
Definition: RelAlgDag.h:573
#define TRANSIENT_DICT_ID
Definition: sqltypes.h:334
static std::shared_ptr< Analyzer::Expr > analyzeValue(const std::string &stringval, const bool is_null)
Definition: ParserNode.cpp:142
DEVICE auto lower_bound(ARGS &&...args)
Definition: gpu_enabled.h:78
#define CHECK_LE(x, y)
Definition: Logger.h:233
const RexWindowBound & getFrameStartBound() const
Definition: RelAlgDag.h:602
std::shared_ptr< Analyzer::Expr > translateOverlapsOper(const RexOperator *) const
std::shared_ptr< Analyzer::Expr > translateUnaryGeoConstructor(const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
std::shared_ptr< Analyzer::Expr > translateArrayFunction(const RexFunctionOperator *) const
static std::shared_ptr< Analyzer::Expr > get(std::shared_ptr< Analyzer::Expr > arg_expr, std::shared_ptr< Analyzer::Expr > like_expr, std::shared_ptr< Analyzer::Expr > escape_expr, const bool is_ilike, const bool is_not)
Definition: ParserNode.cpp:691
std::pair< std::type_index, Handler > IndexedHandler
static RelRexToStringConfig defaults()
Definition: RelAlgDag.h:49
Datum get_constval() const
Definition: Analyzer.h:343
std::shared_ptr< Analyzer::Expr > translateCurrentUser(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateSampleRatio(const RexFunctionOperator *) const
SqlWindowFunctionKind getKind() const
Definition: RelAlgDag.h:571
std::shared_ptr< Analyzer::Expr > translateLike(const RexFunctionOperator *) const
const RelAlgNode * getSourceNode() const
Definition: RelAlgDag.h:351
Definition: sqltypes.h:55
bool takes_arg(const TargetInfo &target_info)
static std::shared_ptr< Analyzer::Expr > analyzeValue(const int64_t numericval, const int scale, const int precision)
Definition: ParserNode.cpp:186
ExtractField
std::shared_ptr< Analyzer::Expr > translateLikely(const RexFunctionOperator *) const
Definition: sqldefs.h:52
std::shared_ptr< Analyzer::Expr > get_in_values_expr(std::shared_ptr< Analyzer::Expr > arg, const ResultSet &val_set)
static std::shared_ptr< Analyzer::Expr > get(const int64_t)
Definition: ParserNode.cpp:222
bool isDistinct() const
Definition: RelAlgDag.h:751
void set_notnull(bool n)
Definition: sqltypes.h:521
static constexpr int64_t kMilliSecsPerHour
#define CHECK(condition)
Definition: Logger.h:222
std::shared_ptr< Analyzer::Expr > translateTernaryGeoFunction(const RexFunctionOperator *) const
const ConstRexScalarPtrVector & getOrderKeys() const
Definition: RelAlgDag.h:583
std::vector< std::shared_ptr< Analyzer::Expr > > qual_to_disjunctive_form(const std::shared_ptr< Analyzer::Expr > &qual_expr)
std::shared_ptr< Analyzer::Expr > translateBinaryGeoFunction(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Constant > make_fp_constant(const int64_t val, const SQLTypeInfo &ti)
std::pair< Datum, bool > datum_from_scalar_tv(const ScalarTargetValue *scalar_tv, const SQLTypeInfo &ti) noexcept
std::shared_ptr< Analyzer::Expr > translateWidthBucket(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateInOper(const RexOperator *) const
uint64_t exp_to_scale(const unsigned exp)
size_t size() const
Definition: RelAlgDag.h:753
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
std::vector< ExpressionPtr > ExpressionPtrVector
Definition: Analyzer.h:189
bool g_cluster
Definition: sqldefs.h:32
const Expr * get_left_operand() const
Definition: Analyzer.h:450
bool isRows() const
Definition: RelAlgDag.h:606
std::shared_ptr< Analyzer::Expr > translateCase(const RexCase *) const
std::shared_ptr< Analyzer::Expr > translateFunctionWithGeoArg(const RexFunctionOperator *) const
Definition: sqltypes.h:59
std::shared_ptr< const query_state::QueryState > query_state_
const std::string & getName() const
Definition: RelAlgDag.h:452
std::shared_ptr< Analyzer::Expr > translateCurrentDate() const
std::string get_datetimeplus_rewrite_funcname(const SQLOps &op)
void validate_datetime_datepart_argument(const std::shared_ptr< Analyzer::Constant > literal_expr)
std::shared_ptr< Analyzer::Expr > translateCardinality(const RexFunctionOperator *) const
Definition: sqldefs.h:75
int cpu_threads()
Definition: thread_count.h:25
const bool just_explain_
const std::vector< TargetMetaInfo > & getOutputMetainfo() const
Definition: RelAlgDag.h:810
bool is_decimal() const
Definition: sqltypes.h:603
std::shared_ptr< Analyzer::Expr > translateGeoComparison(const RexOperator *) const
std::shared_ptr< Analyzer::Expr > translateDatePlusMinus(const RexOperator *) const
const std::list< std::shared_ptr< Analyzer::Expr > > simple_quals
std::shared_ptr< Analyzer::Expr > translateHPTLiteral(const RexFunctionOperator *) const
Definition: sqldefs.h:73
bool is_distinct(const size_t input_idx, const RelAlgNode *node)
int32_t getIdOfString(const std::string &str) const
std::shared_ptr< Analyzer::Expr > translateDatepart(const RexFunctionOperator *) const
bool can_use_parallel_algorithms(const ResultSet &rows)
Definition: ResultSet.cpp:1463
std::shared_ptr< Analyzer::Expr > translateBinaryGeoConstructor(const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
Definition: sqldefs.h:38
std::shared_ptr< Analyzer::Expr > rewrite_to_date_trunc(const Analyzer::FunctionOper *dt_plus)
SQLTypeInfo ext_arg_type_to_type_info(const ExtArgumentType ext_arg_type)
#define VLOG(n)
Definition: Logger.h:316
DateaddField to_dateadd_field(const std::string &field)
std::shared_ptr< Analyzer::Expr > fold_expr(const Analyzer::Expr *expr)
void set_precision(int d)
Definition: sqltypes.h:517
#define IS_COMPARISON(X)
Definition: sqldefs.h:57
double doubleval
Definition: sqltypes.h:237
void fill_integer_in_vals(std::vector< int64_t > &in_vals, std::atomic< size_t > &total_in_vals_count, const ResultSet *values_rowset, const std::pair< int64_t, int64_t > values_rowset_slice)
const Catalog_Namespace::Catalog & cat_
std::shared_ptr< Analyzer::Expr > translateKeyForString(const RexFunctionOperator *) const
static std::shared_ptr< Analyzer::Expr > translateAggregateRex(const RexAgg *rex, const std::vector< std::shared_ptr< Analyzer::Expr >> &scalar_sources)
std::shared_ptr< Analyzer::Expr > translateWindowFunction(const RexWindowFunctionOperator *) const
const std::shared_ptr< Analyzer::Expr > generate() const
std::shared_ptr< Analyzer::Expr > translateScalarSubquery(const RexSubQuery *) const
boost::variant< int64_t, double, float, NullableString > ScalarTargetValue
Definition: TargetValue.h:180
std::shared_ptr< Analyzer::Expr > translateLength(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateExtract(const RexFunctionOperator *) const
ExtractField determineTimeUnit(const SQLTypes &window_frame_bound_type, const Analyzer::Constant *const_expr)
HOST DEVICE void set_type(SQLTypes t)
Definition: sqltypes.h:514