OmniSciDB  eb3a3d0a03
 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 2017 MapD Technologies, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "RelAlgTranslator.h"
18 #include "Shared/SqlTypesLayout.h"
19 
21 #include "DateTimePlusRewrite.h"
22 #include "DateTimeTranslator.h"
24 #include "ExpressionRewrite.h"
27 #include "RelAlgDagBuilder.h"
28 #include "WindowContext.h"
29 
30 #include <future>
31 
32 #include "Analyzer/Analyzer.h"
33 #include "Parser/ParserNode.h"
34 #include "Shared/likely.h"
35 #include "Shared/thread_count.h"
36 
37 extern bool g_enable_watchdog;
38 
40 
41 namespace {
42 
44  const int scale,
45  const int precision) {
46  SQLTypeInfo ti(sql_type, 0, 0, true);
47  if (ti.is_decimal()) {
48  ti.set_scale(scale);
49  ti.set_precision(precision);
50  }
51  return ti;
52 }
53 
54 std::pair<std::shared_ptr<Analyzer::Expr>, SQLQualifier> get_quantified_rhs(
55  const RexScalar* rex_scalar,
56  const RelAlgTranslator& translator) {
57  std::shared_ptr<Analyzer::Expr> rhs;
58  SQLQualifier sql_qual{kONE};
59  const auto rex_operator = dynamic_cast<const RexOperator*>(rex_scalar);
60  if (!rex_operator) {
61  return std::make_pair(rhs, sql_qual);
62  }
63  const auto rex_function = dynamic_cast<const RexFunctionOperator*>(rex_operator);
64  const auto qual_str = rex_function ? rex_function->getName() : "";
65  if (qual_str == "PG_ANY"sv || qual_str == "PG_ALL"sv) {
66  CHECK_EQ(size_t(1), rex_function->size());
67  rhs = translator.translateScalarRex(rex_function->getOperand(0));
68  sql_qual = (qual_str == "PG_ANY"sv) ? kANY : kALL;
69  }
70  if (!rhs && rex_operator->getOperator() == kCAST) {
71  CHECK_EQ(size_t(1), rex_operator->size());
72  std::tie(rhs, sql_qual) = get_quantified_rhs(rex_operator->getOperand(0), translator);
73  }
74  return std::make_pair(rhs, sql_qual);
75 }
76 
77 std::pair<Datum, bool> datum_from_scalar_tv(const ScalarTargetValue* scalar_tv,
78  const SQLTypeInfo& ti) noexcept {
79  Datum d{0};
80  bool is_null_const{false};
81  switch (ti.get_type()) {
82  case kBOOLEAN: {
83  const auto ival = boost::get<int64_t>(scalar_tv);
84  CHECK(ival);
85  if (*ival == inline_int_null_val(ti)) {
86  is_null_const = true;
87  } else {
88  d.boolval = *ival;
89  }
90  break;
91  }
92  case kTINYINT: {
93  const auto ival = boost::get<int64_t>(scalar_tv);
94  CHECK(ival);
95  if (*ival == inline_int_null_val(ti)) {
96  is_null_const = true;
97  } else {
98  d.tinyintval = *ival;
99  }
100  break;
101  }
102  case kSMALLINT: {
103  const auto ival = boost::get<int64_t>(scalar_tv);
104  CHECK(ival);
105  if (*ival == inline_int_null_val(ti)) {
106  is_null_const = true;
107  } else {
108  d.smallintval = *ival;
109  }
110  break;
111  }
112  case kINT: {
113  const auto ival = boost::get<int64_t>(scalar_tv);
114  CHECK(ival);
115  if (*ival == inline_int_null_val(ti)) {
116  is_null_const = true;
117  } else {
118  d.intval = *ival;
119  }
120  break;
121  }
122  case kDECIMAL:
123  case kNUMERIC:
124  case kBIGINT:
125  case kDATE:
126  case kTIME:
127  case kTIMESTAMP: {
128  const auto ival = boost::get<int64_t>(scalar_tv);
129  CHECK(ival);
130  if (*ival == inline_int_null_val(ti)) {
131  is_null_const = true;
132  } else {
133  d.bigintval = *ival;
134  }
135  break;
136  }
137  case kDOUBLE: {
138  const auto dval = boost::get<double>(scalar_tv);
139  CHECK(dval);
140  if (*dval == inline_fp_null_val(ti)) {
141  is_null_const = true;
142  } else {
143  d.doubleval = *dval;
144  }
145  break;
146  }
147  case kFLOAT: {
148  const auto fval = boost::get<float>(scalar_tv);
149  CHECK(fval);
150  if (*fval == inline_fp_null_val(ti)) {
151  is_null_const = true;
152  } else {
153  d.floatval = *fval;
154  }
155  break;
156  }
157  case kTEXT:
158  case kVARCHAR:
159  case kCHAR: {
160  auto nullable_sptr = boost::get<NullableString>(scalar_tv);
161  CHECK(nullable_sptr);
162  if (boost::get<void*>(nullable_sptr)) {
163  is_null_const = true;
164  } else {
165  auto sptr = boost::get<std::string>(nullable_sptr);
166  d.stringval = new std::string(*sptr);
167  }
168  break;
169  }
170  default:
171  CHECK(false) << "Unhandled type: " << ti.get_type_name();
172  }
173  return {d, is_null_const};
174 }
175 
176 } // namespace
177 
178 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateScalarRex(
179  const RexScalar* rex) const {
180  const auto rex_input = dynamic_cast<const RexInput*>(rex);
181  if (rex_input) {
182  return translateInput(rex_input);
183  }
184  const auto rex_literal = dynamic_cast<const RexLiteral*>(rex);
185  if (rex_literal) {
186  return translateLiteral(rex_literal);
187  }
188  const auto rex_window_function = dynamic_cast<const RexWindowFunctionOperator*>(rex);
189  if (rex_window_function) {
190  return translateWindowFunction(rex_window_function);
191  }
192  const auto rex_function = dynamic_cast<const RexFunctionOperator*>(rex);
193  if (rex_function) {
194  return translateFunction(rex_function);
195  }
196  const auto rex_operator = dynamic_cast<const RexOperator*>(rex);
197  if (rex_operator) {
198  return translateOper(rex_operator);
199  }
200  const auto rex_case = dynamic_cast<const RexCase*>(rex);
201  if (rex_case) {
202  return translateCase(rex_case);
203  }
204  const auto rex_subquery = dynamic_cast<const RexSubQuery*>(rex);
205  if (rex_subquery) {
206  return translateScalarSubquery(rex_subquery);
207  }
208  CHECK(false);
209  return nullptr;
210 }
211 
212 namespace {
213 
214 bool is_agg_supported_for_type(const SQLAgg& agg_kind, const SQLTypeInfo& arg_ti) {
215  if ((agg_kind == kMIN || agg_kind == kMAX || agg_kind == kSUM || agg_kind == kAVG) &&
216  !(arg_ti.is_number() || arg_ti.is_boolean() || arg_ti.is_time())) {
217  return false;
218  }
219 
220  return true;
221 }
222 
223 } // namespace
224 
225 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateAggregateRex(
226  const RexAgg* rex,
227  const std::vector<std::shared_ptr<Analyzer::Expr>>& scalar_sources) {
228  SQLAgg agg_kind = rex->getKind();
229  const bool is_distinct = rex->isDistinct();
230  const bool takes_arg{rex->size() > 0};
231  std::shared_ptr<Analyzer::Expr> arg_expr;
232  std::shared_ptr<Analyzer::Constant> arg1; // 2nd aggregate parameter
233  if (takes_arg) {
234  const auto operand = rex->getOperand(0);
235  CHECK_LT(operand, scalar_sources.size());
236  CHECK_LE(rex->size(), 2u);
237  arg_expr = scalar_sources[operand];
238  if (agg_kind == kAPPROX_COUNT_DISTINCT && rex->size() == 2) {
239  arg1 = std::dynamic_pointer_cast<Analyzer::Constant>(
240  scalar_sources[rex->getOperand(1)]);
241  if (!arg1 || arg1->get_type_info().get_type() != kINT ||
242  arg1->get_constval().intval < 1 || arg1->get_constval().intval > 100) {
243  throw std::runtime_error(
244  "APPROX_COUNT_DISTINCT's second parameter should be SMALLINT literal between "
245  "1 and 100");
246  }
247  } else if (agg_kind == kAPPROX_QUANTILE) {
248  if (g_cluster) {
249  throw std::runtime_error(
250  "APPROX_PERCENTILE/MEDIAN is not supported in distributed mode at this "
251  "time.");
252  }
253  // If second parameter is not given then APPROX_MEDIAN is assumed.
254  if (rex->size() == 2) {
255  arg1 = std::dynamic_pointer_cast<Analyzer::Constant>(
256  std::dynamic_pointer_cast<Analyzer::Constant>(
257  scalar_sources[rex->getOperand(1)])
258  ->add_cast(SQLTypeInfo(kDOUBLE)));
259  } else {
260  constexpr Datum median{.doubleval = 0.5};
261  arg1 = std::make_shared<Analyzer::Constant>(kDOUBLE, false, median);
262  }
263  }
264  const auto& arg_ti = arg_expr->get_type_info();
265  if (!is_agg_supported_for_type(agg_kind, arg_ti)) {
266  throw std::runtime_error("Aggregate on " + arg_ti.get_type_name() +
267  " is not supported yet.");
268  }
269  }
270  const auto agg_ti = get_agg_type(agg_kind, arg_expr.get());
271  return makeExpr<Analyzer::AggExpr>(agg_ti, agg_kind, arg_expr, is_distinct, arg1);
272 }
273 
274 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateLiteral(
275  const RexLiteral* rex_literal) {
276  auto lit_ti = build_type_info(
277  rex_literal->getType(), rex_literal->getScale(), rex_literal->getPrecision());
278  auto target_ti = build_type_info(rex_literal->getTargetType(),
279  rex_literal->getTargetScale(),
280  rex_literal->getTargetPrecision());
281  switch (rex_literal->getType()) {
282  case kINT:
283  case kBIGINT: {
284  Datum d;
285  d.bigintval = rex_literal->getVal<int64_t>();
286  return makeExpr<Analyzer::Constant>(rex_literal->getType(), false, d);
287  }
288  case kDECIMAL: {
289  const auto val = rex_literal->getVal<int64_t>();
290  const int precision = rex_literal->getPrecision();
291  const int scale = rex_literal->getScale();
292  if (target_ti.is_fp() && !scale) {
293  return make_fp_constant(val, target_ti);
294  }
295  auto lit_expr = scale ? Parser::FixedPtLiteral::analyzeValue(val, scale, precision)
297  return lit_ti != target_ti ? lit_expr->add_cast(target_ti) : lit_expr;
298  }
299  case kTEXT: {
300  return Parser::StringLiteral::analyzeValue(rex_literal->getVal<std::string>());
301  }
302  case kBOOLEAN: {
303  Datum d;
304  d.boolval = rex_literal->getVal<bool>();
305  return makeExpr<Analyzer::Constant>(kBOOLEAN, false, d);
306  }
307  case kDOUBLE: {
308  Datum d;
309  d.doubleval = rex_literal->getVal<double>();
310  auto lit_expr = makeExpr<Analyzer::Constant>(kDOUBLE, false, d);
311  return lit_ti != target_ti ? lit_expr->add_cast(target_ti) : lit_expr;
312  }
313  case kINTERVAL_DAY_TIME:
314  case kINTERVAL_YEAR_MONTH: {
315  Datum d;
316  d.bigintval = rex_literal->getVal<int64_t>();
317  return makeExpr<Analyzer::Constant>(rex_literal->getType(), false, d);
318  }
319  case kTIME:
320  case kTIMESTAMP: {
321  Datum d;
322  d.bigintval =
323  rex_literal->getType() == kTIMESTAMP && rex_literal->getPrecision() > 0
324  ? rex_literal->getVal<int64_t>()
325  : rex_literal->getVal<int64_t>() / 1000;
326  return makeExpr<Analyzer::Constant>(
327  SQLTypeInfo(rex_literal->getType(), rex_literal->getPrecision(), 0, false),
328  false,
329  d);
330  }
331  case kDATE: {
332  Datum d;
333  d.bigintval = rex_literal->getVal<int64_t>() * 24 * 3600;
334  return makeExpr<Analyzer::Constant>(rex_literal->getType(), false, d);
335  }
336  case kNULLT: {
337  if (target_ti.is_array()) {
339  // defaulting to valid sub-type for convenience
340  target_ti.set_subtype(kBOOLEAN);
341  return makeExpr<Analyzer::ArrayExpr>(target_ti, args, true);
342  }
343  return makeExpr<Analyzer::Constant>(rex_literal->getTargetType(), true, Datum{0});
344  }
345  default: {
346  LOG(FATAL) << "Unexpected literal type " << lit_ti.get_type_name();
347  }
348  }
349  return nullptr;
350 }
351 
352 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateScalarSubquery(
353  const RexSubQuery* rex_subquery) const {
354  if (just_explain_) {
355  throw std::runtime_error("EXPLAIN is not supported with sub-queries");
356  }
357  CHECK(rex_subquery);
358  auto result = rex_subquery->getExecutionResult();
359  auto row_set = result->getRows();
360  const size_t row_count = row_set->rowCount();
361  if (row_count > size_t(1)) {
362  throw std::runtime_error("Scalar sub-query returned multiple rows");
363  }
364  if (row_count == size_t(0)) {
365  if (row_set->isValidationOnlyRes()) {
366  Datum d{0};
367  return makeExpr<Analyzer::Constant>(rex_subquery->getType(), false, d);
368  }
369  throw std::runtime_error("Scalar sub-query returned no results");
370  }
371  CHECK_EQ(row_count, size_t(1));
372  row_set->moveToBegin();
373  auto first_row = row_set->getNextRow(false, false);
374  CHECK_EQ(first_row.size(), size_t(1));
375  auto scalar_tv = boost::get<ScalarTargetValue>(&first_row[0]);
376  auto ti = rex_subquery->getType();
377  if (ti.is_string()) {
378  throw std::runtime_error("Scalar sub-queries which return strings not supported");
379  }
380  Datum d{0};
381  bool is_null_const{false};
382  std::tie(d, is_null_const) = datum_from_scalar_tv(scalar_tv, ti);
383  return makeExpr<Analyzer::Constant>(ti, is_null_const, d);
384 }
385 
386 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateInput(
387  const RexInput* rex_input) const {
388  const auto source = rex_input->getSourceNode();
389  const auto it_rte_idx = input_to_nest_level_.find(source);
390  CHECK(it_rte_idx != input_to_nest_level_.end())
391  << "Not found in input_to_nest_level_, source=" << source->toString();
392  const int rte_idx = it_rte_idx->second;
393  const auto scan_source = dynamic_cast<const RelScan*>(source);
394  const auto& in_metainfo = source->getOutputMetainfo();
395  if (scan_source) {
396  // We're at leaf (scan) level and not supposed to have input metadata,
397  // the name and type information come directly from the catalog.
398  CHECK(in_metainfo.empty());
399  const auto table_desc = scan_source->getTableDescriptor();
400  const auto cd =
401  cat_.getMetadataForColumnBySpi(table_desc->tableId, rex_input->getIndex() + 1);
402  CHECK(cd);
403  auto col_ti = cd->columnType;
404  if (col_ti.is_string()) {
405  col_ti.set_type(kTEXT);
406  }
407  if (cd->isVirtualCol) {
408  // TODO(alex): remove at some point, we only need this fixup for backwards
409  // compatibility with old imported data
410  CHECK_EQ("rowid", cd->columnName);
411  col_ti.set_size(8);
412  }
413  CHECK_LE(static_cast<size_t>(rte_idx), join_types_.size());
414  if (rte_idx > 0 && join_types_[rte_idx - 1] == JoinType::LEFT) {
415  col_ti.set_notnull(false);
416  }
417  return std::make_shared<Analyzer::ColumnVar>(
418  col_ti, table_desc->tableId, cd->columnId, rte_idx);
419  }
420  CHECK(!in_metainfo.empty()) << "for " << source->toString();
421  CHECK_GE(rte_idx, 0);
422  const size_t col_id = rex_input->getIndex();
423  CHECK_LT(col_id, in_metainfo.size());
424  auto col_ti = in_metainfo[col_id].get_type_info();
425 
426  if (join_types_.size() > 0) {
427  CHECK_LE(static_cast<size_t>(rte_idx), join_types_.size());
428  if (rte_idx > 0 && join_types_[rte_idx - 1] == JoinType::LEFT) {
429  col_ti.set_notnull(false);
430  }
431  }
432 
433  return std::make_shared<Analyzer::ColumnVar>(col_ti, -source->getId(), col_id, rte_idx);
434 }
435 
436 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateUoper(
437  const RexOperator* rex_operator) const {
438  CHECK_EQ(size_t(1), rex_operator->size());
439  const auto operand_expr = translateScalarRex(rex_operator->getOperand(0));
440  const auto sql_op = rex_operator->getOperator();
441  switch (sql_op) {
442  case kCAST: {
443  const auto& target_ti = rex_operator->getType();
444  CHECK_NE(kNULLT, target_ti.get_type());
445  const auto& operand_ti = operand_expr->get_type_info();
446  if (operand_ti.is_string() && target_ti.is_string()) {
447  return operand_expr;
448  }
449  if (target_ti.is_time() ||
450  operand_ti
451  .is_string()) { // TODO(alex): check and unify with the rest of the cases
452  // Do not propogate encoding on small dates
453  return target_ti.is_date_in_days()
454  ? operand_expr->add_cast(SQLTypeInfo(kDATE, false))
455  : operand_expr->add_cast(target_ti);
456  }
457  if (!operand_ti.is_string() && target_ti.is_string()) {
458  return operand_expr->add_cast(target_ti);
459  }
460 
461  return std::make_shared<Analyzer::UOper>(target_ti, false, sql_op, operand_expr);
462  }
463  case kNOT:
464  case kISNULL: {
465  return std::make_shared<Analyzer::UOper>(kBOOLEAN, sql_op, operand_expr);
466  }
467  case kISNOTNULL: {
468  auto is_null = std::make_shared<Analyzer::UOper>(kBOOLEAN, kISNULL, operand_expr);
469  return std::make_shared<Analyzer::UOper>(kBOOLEAN, kNOT, is_null);
470  }
471  case kMINUS: {
472  const auto& ti = operand_expr->get_type_info();
473  return std::make_shared<Analyzer::UOper>(ti, false, kUMINUS, operand_expr);
474  }
475  case kUNNEST: {
476  const auto& ti = operand_expr->get_type_info();
477  CHECK(ti.is_array());
478  return makeExpr<Analyzer::UOper>(ti.get_elem_type(), false, kUNNEST, operand_expr);
479  }
480  default:
481  CHECK(false);
482  }
483  return nullptr;
484 }
485 
486 namespace {
487 
488 std::shared_ptr<Analyzer::Expr> get_in_values_expr(std::shared_ptr<Analyzer::Expr> arg,
489  const ResultSet& val_set) {
491  return nullptr;
492  }
493  if (val_set.rowCount() > 5000000 && g_enable_watchdog) {
494  throw std::runtime_error(
495  "Unable to handle 'expr IN (subquery)', subquery returned 5M+ rows.");
496  }
497  std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
498  const size_t fetcher_count = cpu_threads();
499  std::vector<std::list<std::shared_ptr<Analyzer::Expr>>> expr_set(
500  fetcher_count, std::list<std::shared_ptr<Analyzer::Expr>>());
501  std::vector<std::future<void>> fetcher_threads;
502  const auto& ti = arg->get_type_info();
503  const auto entry_count = val_set.entryCount();
504  for (size_t i = 0,
505  start_entry = 0,
506  stride = (entry_count + fetcher_count - 1) / fetcher_count;
507  i < fetcher_count && start_entry < entry_count;
508  ++i, start_entry += stride) {
509  const auto end_entry = std::min(start_entry + stride, entry_count);
510  fetcher_threads.push_back(std::async(
512  [&](std::list<std::shared_ptr<Analyzer::Expr>>& in_vals,
513  const size_t start,
514  const size_t end) {
515  for (auto index = start; index < end; ++index) {
516  auto row = val_set.getRowAt(index);
517  if (row.empty()) {
518  continue;
519  }
520  auto scalar_tv = boost::get<ScalarTargetValue>(&row[0]);
521  Datum d{0};
522  bool is_null_const{false};
523  std::tie(d, is_null_const) = datum_from_scalar_tv(scalar_tv, ti);
524  if (ti.is_string() && ti.get_compression() != kENCODING_NONE) {
525  auto ti_none_encoded = ti;
526  ti_none_encoded.set_compression(kENCODING_NONE);
527  auto none_encoded_string =
528  makeExpr<Analyzer::Constant>(ti, is_null_const, d);
529  auto dict_encoded_string = std::make_shared<Analyzer::UOper>(
530  ti, false, kCAST, none_encoded_string);
531  in_vals.push_back(dict_encoded_string);
532  } else {
533  in_vals.push_back(makeExpr<Analyzer::Constant>(ti, is_null_const, d));
534  }
535  }
536  },
537  std::ref(expr_set[i]),
538  start_entry,
539  end_entry));
540  }
541  for (auto& child : fetcher_threads) {
542  child.get();
543  }
544 
545  val_set.moveToBegin();
546  for (auto& exprs : expr_set) {
547  value_exprs.splice(value_exprs.end(), exprs);
548  }
549  return makeExpr<Analyzer::InValues>(arg, value_exprs);
550 }
551 
552 } // namespace
553 
554 // Creates an Analyzer expression for an IN subquery which subsequently goes through the
555 // regular Executor::codegen() mechanism. The creation of the expression out of
556 // subquery's result set is parallelized whenever possible. In addition, take advantage
557 // of additional information that elements in the right hand side are constants; see
558 // getInIntegerSetExpr().
559 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateInOper(
560  const RexOperator* rex_operator) const {
561  if (just_explain_) {
562  throw std::runtime_error("EXPLAIN is not supported with sub-queries");
563  }
564  CHECK(rex_operator->size() == 2);
565  const auto lhs = translateScalarRex(rex_operator->getOperand(0));
566  const auto rhs = rex_operator->getOperand(1);
567  const auto rex_subquery = dynamic_cast<const RexSubQuery*>(rhs);
568  CHECK(rex_subquery);
569  auto ti = lhs->get_type_info();
570  auto result = rex_subquery->getExecutionResult();
571  CHECK(result);
572  auto& row_set = result->getRows();
573  CHECK_EQ(size_t(1), row_set->colCount());
574  const auto& rhs_ti = row_set->getColType(0);
575  if (rhs_ti.get_type() != ti.get_type()) {
576  throw std::runtime_error(
577  "The two sides of the IN operator must have the same type; found " +
578  ti.get_type_name() + " and " + rhs_ti.get_type_name());
579  }
580  row_set->moveToBegin();
581  if (row_set->entryCount() > 10000) {
582  std::shared_ptr<Analyzer::Expr> expr;
583  if ((ti.is_integer() || (ti.is_string() && ti.get_compression() == kENCODING_DICT)) &&
584  !row_set->getQueryMemDesc().didOutputColumnar()) {
585  expr = getInIntegerSetExpr(lhs, *row_set);
586  // Handle the highly unlikely case when the InIntegerSet ended up being tiny.
587  // Just let it fall through the usual InValues path at the end of this method,
588  // its codegen knows to use inline comparisons for few values.
589  if (expr && std::static_pointer_cast<Analyzer::InIntegerSet>(expr)
590  ->get_value_list()
591  .size() <= 100) {
592  expr = nullptr;
593  }
594  } else {
595  expr = get_in_values_expr(lhs, *row_set);
596  }
597  if (expr) {
598  return expr;
599  }
600  }
601  std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
602  while (true) {
603  auto row = row_set->getNextRow(true, false);
604  if (row.empty()) {
605  break;
606  }
607  if (g_enable_watchdog && value_exprs.size() >= 10000) {
608  throw std::runtime_error(
609  "Unable to handle 'expr IN (subquery)', subquery returned 10000+ rows.");
610  }
611  auto scalar_tv = boost::get<ScalarTargetValue>(&row[0]);
612  Datum d{0};
613  bool is_null_const{false};
614  std::tie(d, is_null_const) = datum_from_scalar_tv(scalar_tv, ti);
615  if (ti.is_string() && ti.get_compression() != kENCODING_NONE) {
616  auto ti_none_encoded = ti;
617  ti_none_encoded.set_compression(kENCODING_NONE);
618  auto none_encoded_string = makeExpr<Analyzer::Constant>(ti, is_null_const, d);
619  auto dict_encoded_string =
620  std::make_shared<Analyzer::UOper>(ti, false, kCAST, none_encoded_string);
621  value_exprs.push_back(dict_encoded_string);
622  } else {
623  value_exprs.push_back(makeExpr<Analyzer::Constant>(ti, is_null_const, d));
624  }
625  }
626  return makeExpr<Analyzer::InValues>(lhs, value_exprs);
627 }
628 
629 namespace {
630 
631 const size_t g_max_integer_set_size{1 << 25};
632 
634  std::vector<int64_t>& in_vals,
635  std::atomic<size_t>& total_in_vals_count,
636  const ResultSet* values_rowset,
637  const std::pair<int64_t, int64_t> values_rowset_slice,
638  const StringDictionaryProxy* source_dict,
639  const StringDictionaryProxy* dest_dict,
640  const int64_t needle_null_val) {
641  CHECK(in_vals.empty());
642  bool dicts_are_equal = source_dict == dest_dict;
643  for (auto index = values_rowset_slice.first; index < values_rowset_slice.second;
644  ++index) {
645  const auto row = values_rowset->getOneColRow(index);
646  if (UNLIKELY(!row.valid)) {
647  continue;
648  }
649  if (dicts_are_equal) {
650  in_vals.push_back(row.value);
651  } else {
652  const int string_id =
653  row.value == needle_null_val
654  ? needle_null_val
655  : dest_dict->getIdOfString(source_dict->getString(row.value));
656  if (string_id != StringDictionary::INVALID_STR_ID) {
657  in_vals.push_back(string_id);
658  }
659  }
660  if (UNLIKELY(g_enable_watchdog && (in_vals.size() & 1023) == 0 &&
661  total_in_vals_count.fetch_add(1024) >= g_max_integer_set_size)) {
662  throw std::runtime_error(
663  "Unable to handle 'expr IN (subquery)', subquery returned 30M+ rows.");
664  }
665  }
666 }
667 
668 void fill_integer_in_vals(std::vector<int64_t>& in_vals,
669  std::atomic<size_t>& total_in_vals_count,
670  const ResultSet* values_rowset,
671  const std::pair<int64_t, int64_t> values_rowset_slice) {
672  CHECK(in_vals.empty());
673  for (auto index = values_rowset_slice.first; index < values_rowset_slice.second;
674  ++index) {
675  const auto row = values_rowset->getOneColRow(index);
676  if (row.valid) {
677  in_vals.push_back(row.value);
678  if (UNLIKELY(g_enable_watchdog && (in_vals.size() & 1023) == 0 &&
679  total_in_vals_count.fetch_add(1024) >= g_max_integer_set_size)) {
680  throw std::runtime_error(
681  "Unable to handle 'expr IN (subquery)', subquery returned 30M+ rows.");
682  }
683  }
684  }
685 }
686 
687 // Multi-node counterpart of the other version. Saves round-trips, which is crucial
688 // for a big right-hand side result. It only handles physical string dictionary ids,
689 // therefore it won't be able to handle a right-hand side sub-query with a CASE
690 // returning literals on some branches. That case isn't hard too handle either, but
691 // it's not clear it's actually important in practice.
692 // RelAlgTranslator::getInIntegerSetExpr makes sure, by checking the encodings, that
693 // this function isn't called in such cases.
695  std::vector<int64_t>& in_vals,
696  std::atomic<size_t>& total_in_vals_count,
697  const ResultSet* values_rowset,
698  const std::pair<int64_t, int64_t> values_rowset_slice,
699  const std::vector<LeafHostInfo>& leaf_hosts,
700  const DictRef source_dict_ref,
701  const DictRef dest_dict_ref,
702  const int32_t dest_generation,
703  const int64_t needle_null_val) {
704  CHECK(in_vals.empty());
705  std::vector<int32_t> source_ids;
706  source_ids.reserve(values_rowset->entryCount());
707  bool has_nulls = false;
708  if (source_dict_ref == dest_dict_ref) {
709  in_vals.reserve(values_rowset_slice.second - values_rowset_slice.first +
710  1); // Add 1 to cover interval
711  for (auto index = values_rowset_slice.first; index < values_rowset_slice.second;
712  ++index) {
713  const auto row = values_rowset->getOneColRow(index);
714  if (!row.valid) {
715  continue;
716  }
717  if (row.value != needle_null_val) {
718  in_vals.push_back(row.value);
719  if (UNLIKELY(g_enable_watchdog && (in_vals.size() & 1023) == 0 &&
720  total_in_vals_count.fetch_add(1024) >= g_max_integer_set_size)) {
721  throw std::runtime_error(
722  "Unable to handle 'expr IN (subquery)', subquery returned 30M+ rows.");
723  }
724  } else {
725  has_nulls = true;
726  }
727  }
728  if (has_nulls) {
729  in_vals.push_back(
730  needle_null_val); // we've deduped null values as an optimization, although
731  // this is not required by consumer
732  }
733  return;
734  }
735  // Code path below is for when dictionaries are not shared
736  for (auto index = values_rowset_slice.first; index < values_rowset_slice.second;
737  ++index) {
738  const auto row = values_rowset->getOneColRow(index);
739  if (row.valid) {
740  if (row.value != needle_null_val) {
741  source_ids.push_back(row.value);
742  } else {
743  has_nulls = true;
744  }
745  }
746  }
747  std::vector<int32_t> dest_ids;
748  translate_string_ids(dest_ids,
749  leaf_hosts.front(),
750  dest_dict_ref,
751  source_ids,
752  source_dict_ref,
753  dest_generation);
754  CHECK_EQ(dest_ids.size(), source_ids.size());
755  in_vals.reserve(dest_ids.size() + (has_nulls ? 1 : 0));
756  if (has_nulls) {
757  in_vals.push_back(needle_null_val);
758  }
759  for (const int32_t dest_id : dest_ids) {
760  if (dest_id != StringDictionary::INVALID_STR_ID) {
761  in_vals.push_back(dest_id);
762  if (UNLIKELY(g_enable_watchdog && (in_vals.size() & 1023) == 0 &&
763  total_in_vals_count.fetch_add(1024) >= g_max_integer_set_size)) {
764  throw std::runtime_error(
765  "Unable to handle 'expr IN (subquery)', subquery returned 30M+ rows.");
766  }
767  }
768  }
769 }
770 
771 } // namespace
772 
773 // The typical IN subquery involves either dictionary-encoded strings or integers.
774 // Analyzer::InValues is a very heavy representation of the right hand side of such
775 // a query since we already know the right hand would be a list of Analyzer::Constant
776 // shared pointers. We can avoid the big overhead of each Analyzer::Constant and the
777 // refcounting associated with shared pointers by creating an abbreviated InIntegerSet
778 // representation of the IN expression which takes advantage of the this information.
779 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::getInIntegerSetExpr(
780  std::shared_ptr<Analyzer::Expr> arg,
781  const ResultSet& val_set) const {
783  return nullptr;
784  }
785  std::vector<int64_t> value_exprs;
786  const size_t fetcher_count = cpu_threads();
787  std::vector<std::vector<int64_t>> expr_set(fetcher_count);
788  std::vector<std::future<void>> fetcher_threads;
789  const auto& arg_type = arg->get_type_info();
790  const auto entry_count = val_set.entryCount();
791  CHECK_EQ(size_t(1), val_set.colCount());
792  const auto& col_type = val_set.getColType(0);
793  if (g_cluster && arg_type.is_string() &&
794  (col_type.get_comp_param() <= 0 || arg_type.get_comp_param() <= 0)) {
795  // Skip this case for now, see comment for fill_dictionary_encoded_in_vals.
796  return nullptr;
797  }
798  std::atomic<size_t> total_in_vals_count{0};
799  for (size_t i = 0,
800  start_entry = 0,
801  stride = (entry_count + fetcher_count - 1) / fetcher_count;
802  i < fetcher_count && start_entry < entry_count;
803  ++i, start_entry += stride) {
804  expr_set[i].reserve(entry_count / fetcher_count);
805  const auto end_entry = std::min(start_entry + stride, entry_count);
806  if (arg_type.is_string()) {
807  CHECK_EQ(kENCODING_DICT, arg_type.get_compression());
808  // const int32_t dest_dict_id = arg_type.get_comp_param();
809  // const int32_t source_dict_id = col_type.get_comp_param();
810  const DictRef dest_dict_ref(arg_type.get_comp_param(), cat_.getDatabaseId());
811  const DictRef source_dict_ref(col_type.get_comp_param(), cat_.getDatabaseId());
812  const auto dd = executor_->getStringDictionaryProxy(
813  arg_type.get_comp_param(), val_set.getRowSetMemOwner(), true);
814  const auto sd = executor_->getStringDictionaryProxy(
815  col_type.get_comp_param(), val_set.getRowSetMemOwner(), true);
816  CHECK(sd);
817  const auto needle_null_val = inline_int_null_val(arg_type);
818  fetcher_threads.push_back(std::async(
820  [this,
821  &val_set,
822  &total_in_vals_count,
823  sd,
824  dd,
825  source_dict_ref,
826  dest_dict_ref,
827  needle_null_val](
828  std::vector<int64_t>& in_vals, const size_t start, const size_t end) {
829  if (g_cluster) {
830  CHECK_GE(dd->getGeneration(), 0);
832  total_in_vals_count,
833  &val_set,
834  {start, end},
836  source_dict_ref,
837  dest_dict_ref,
838  dd->getGeneration(),
839  needle_null_val);
840  } else {
842  total_in_vals_count,
843  &val_set,
844  {start, end},
845  sd,
846  dd,
847  needle_null_val);
848  }
849  },
850  std::ref(expr_set[i]),
851  start_entry,
852  end_entry));
853  } else {
854  CHECK(arg_type.is_integer());
855  fetcher_threads.push_back(std::async(
857  [&val_set, &total_in_vals_count](
858  std::vector<int64_t>& in_vals, const size_t start, const size_t end) {
859  fill_integer_in_vals(in_vals, total_in_vals_count, &val_set, {start, end});
860  },
861  std::ref(expr_set[i]),
862  start_entry,
863  end_entry));
864  }
865  }
866  for (auto& child : fetcher_threads) {
867  child.get();
868  }
869 
870  val_set.moveToBegin();
871  value_exprs.reserve(entry_count);
872  for (auto& exprs : expr_set) {
873  value_exprs.insert(value_exprs.end(), exprs.begin(), exprs.end());
874  }
875  return makeExpr<Analyzer::InIntegerSet>(
876  arg, value_exprs, arg_type.get_notnull() && col_type.get_notnull());
877 }
878 
879 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateOper(
880  const RexOperator* rex_operator) const {
881  CHECK_GT(rex_operator->size(), size_t(0));
882  if (rex_operator->size() == 1) {
883  return translateUoper(rex_operator);
884  }
885  const auto sql_op = rex_operator->getOperator();
886  if (sql_op == kIN) {
887  return translateInOper(rex_operator);
888  }
889  if (sql_op == kMINUS || sql_op == kPLUS) {
890  auto date_plus_minus = translateDatePlusMinus(rex_operator);
891  if (date_plus_minus) {
892  return date_plus_minus;
893  }
894  }
895  if (sql_op == kOVERLAPS) {
896  return translateOverlapsOper(rex_operator);
897  } else if (IS_COMPARISON(sql_op)) {
898  auto geo_comp = translateGeoComparison(rex_operator);
899  if (geo_comp) {
900  return geo_comp;
901  }
902  }
903  auto lhs = translateScalarRex(rex_operator->getOperand(0));
904  for (size_t i = 1; i < rex_operator->size(); ++i) {
905  std::shared_ptr<Analyzer::Expr> rhs;
906  SQLQualifier sql_qual{kONE};
907  const auto rhs_op = rex_operator->getOperand(i);
908  std::tie(rhs, sql_qual) = get_quantified_rhs(rhs_op, *this);
909  if (!rhs) {
910  rhs = translateScalarRex(rhs_op);
911  }
912  CHECK(rhs);
913  lhs = Parser::OperExpr::normalize(sql_op, sql_qual, lhs, rhs);
914  }
915  return lhs;
916 }
917 
918 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateOverlapsOper(
919  const RexOperator* rex_operator) const {
920  const auto sql_op = rex_operator->getOperator();
921  CHECK(sql_op == kOVERLAPS);
922 
923  const auto lhs = translateScalarRex(rex_operator->getOperand(0));
924  const auto lhs_ti = lhs->get_type_info();
925  if (lhs_ti.is_geometry()) {
926  return translateGeoOverlapsOper(rex_operator);
927  } else {
928  throw std::runtime_error(
929  "Overlaps equivalence is currently only supported for geospatial types");
930  }
931 }
932 
933 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateCase(
934  const RexCase* rex_case) const {
935  std::shared_ptr<Analyzer::Expr> else_expr;
936  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
937  expr_list;
938  for (size_t i = 0; i < rex_case->branchCount(); ++i) {
939  const auto when_expr = translateScalarRex(rex_case->getWhen(i));
940  const auto then_expr = translateScalarRex(rex_case->getThen(i));
941  expr_list.emplace_back(when_expr, then_expr);
942  }
943  if (rex_case->getElse()) {
944  else_expr = translateScalarRex(rex_case->getElse());
945  }
946  return Parser::CaseExpr::normalize(expr_list, else_expr);
947 }
948 
949 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateWidthBucket(
950  const RexFunctionOperator* rex_function) const {
951  CHECK(rex_function->size() == 4);
952  auto target_value = translateScalarRex(rex_function->getOperand(0));
953  auto lower_bound = translateScalarRex(rex_function->getOperand(1));
954  auto upper_bound = translateScalarRex(rex_function->getOperand(2));
955  auto partition_count = translateScalarRex(rex_function->getOperand(3));
956  if (!partition_count->get_type_info().is_integer()) {
957  throw std::runtime_error(
958  "PARTITION_COUNT expression of width_bucket function expects an integer type.");
959  }
960  auto check_numeric_type =
961  [](const std::string& col_name, const Analyzer::Expr* expr, bool allow_null_type) {
962  if (expr->get_type_info().get_type() == kNULLT) {
963  if (!allow_null_type) {
964  throw std::runtime_error(
965  col_name + " expression of width_bucket function expects non-null type.");
966  }
967  return;
968  }
969  if (!expr->get_type_info().is_number()) {
970  throw std::runtime_error(
971  col_name + " expression of width_bucket function expects a numeric type.");
972  }
973  };
974  // target value may have null value
975  check_numeric_type("TARGET_VALUE", target_value.get(), true);
976  check_numeric_type("LOWER_BOUND", lower_bound.get(), false);
977  check_numeric_type("UPPER_BOUND", upper_bound.get(), false);
978 
979  auto cast_to_double_if_necessary = [](std::shared_ptr<Analyzer::Expr> arg) {
980  const auto& arg_ti = arg->get_type_info();
981  if (arg_ti.get_type() != kDOUBLE) {
982  const auto& double_ti = SQLTypeInfo(kDOUBLE, arg_ti.get_notnull());
983  return arg->add_cast(double_ti);
984  }
985  return arg;
986  };
987  target_value = cast_to_double_if_necessary(target_value);
988  lower_bound = cast_to_double_if_necessary(lower_bound);
989  upper_bound = cast_to_double_if_necessary(upper_bound);
990  return makeExpr<Analyzer::WidthBucketExpr>(
991  target_value, lower_bound, upper_bound, partition_count);
992 }
993 
994 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateLike(
995  const RexFunctionOperator* rex_function) const {
996  CHECK(rex_function->size() == 2 || rex_function->size() == 3);
997  const auto arg = translateScalarRex(rex_function->getOperand(0));
998  const auto like = translateScalarRex(rex_function->getOperand(1));
999  if (!std::dynamic_pointer_cast<const Analyzer::Constant>(like)) {
1000  throw std::runtime_error("The matching pattern must be a literal.");
1001  }
1002  const auto escape = (rex_function->size() == 3)
1003  ? translateScalarRex(rex_function->getOperand(2))
1004  : nullptr;
1005  const bool is_ilike = rex_function->getName() == "PG_ILIKE"sv;
1006  return Parser::LikeExpr::get(arg, like, escape, is_ilike, false);
1007 }
1008 
1009 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateRegexp(
1010  const RexFunctionOperator* rex_function) const {
1011  CHECK(rex_function->size() == 2 || rex_function->size() == 3);
1012  const auto arg = translateScalarRex(rex_function->getOperand(0));
1013  const auto pattern = translateScalarRex(rex_function->getOperand(1));
1014  if (!std::dynamic_pointer_cast<const Analyzer::Constant>(pattern)) {
1015  throw std::runtime_error("The matching pattern must be a literal.");
1016  }
1017  const auto escape = (rex_function->size() == 3)
1018  ? translateScalarRex(rex_function->getOperand(2))
1019  : nullptr;
1020  return Parser::RegexpExpr::get(arg, pattern, escape, false);
1021 }
1022 
1023 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateLikely(
1024  const RexFunctionOperator* rex_function) const {
1025  CHECK(rex_function->size() == 1);
1026  const auto arg = translateScalarRex(rex_function->getOperand(0));
1027  return makeExpr<Analyzer::LikelihoodExpr>(arg, 0.9375);
1028 }
1029 
1030 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateUnlikely(
1031  const RexFunctionOperator* rex_function) const {
1032  CHECK(rex_function->size() == 1);
1033  const auto arg = translateScalarRex(rex_function->getOperand(0));
1034  return makeExpr<Analyzer::LikelihoodExpr>(arg, 0.0625);
1035 }
1036 
1037 namespace {
1038 
1040  const std::shared_ptr<Analyzer::Constant> literal_expr) {
1041  if (!literal_expr || literal_expr->get_is_null()) {
1042  throw std::runtime_error("The 'DatePart' argument must be a not 'null' literal.");
1043  }
1044 }
1045 
1046 } // namespace
1047 
1048 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateExtract(
1049  const RexFunctionOperator* rex_function) const {
1050  CHECK_EQ(size_t(2), rex_function->size());
1051  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1052  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1054  const auto from_expr = translateScalarRex(rex_function->getOperand(1));
1055  const bool is_date_trunc = rex_function->getName() == "PG_DATE_TRUNC"sv;
1056  if (is_date_trunc) {
1057  return DateTruncExpr::generate(from_expr, *timeunit_lit->get_constval().stringval);
1058  } else {
1059  return ExtractExpr::generate(from_expr, *timeunit_lit->get_constval().stringval);
1060  }
1061 }
1062 
1063 namespace {
1064 
1065 std::shared_ptr<Analyzer::Constant> makeNumericConstant(const SQLTypeInfo& ti,
1066  const long val) {
1067  CHECK(ti.is_number());
1068  Datum datum{0};
1069  switch (ti.get_type()) {
1070  case kTINYINT: {
1071  datum.tinyintval = val;
1072  break;
1073  }
1074  case kSMALLINT: {
1075  datum.smallintval = val;
1076  break;
1077  }
1078  case kINT: {
1079  datum.intval = val;
1080  break;
1081  }
1082  case kBIGINT: {
1083  datum.bigintval = val;
1084  break;
1085  }
1086  case kDECIMAL:
1087  case kNUMERIC: {
1088  datum.bigintval = val * exp_to_scale(ti.get_scale());
1089  break;
1090  }
1091  case kFLOAT: {
1092  datum.floatval = val;
1093  break;
1094  }
1095  case kDOUBLE: {
1096  datum.doubleval = val;
1097  break;
1098  }
1099  default:
1100  CHECK(false);
1101  }
1102  return makeExpr<Analyzer::Constant>(ti, false, datum);
1103 }
1104 
1105 } // namespace
1106 
1107 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateDateadd(
1108  const RexFunctionOperator* rex_function) const {
1109  CHECK_EQ(size_t(3), rex_function->size());
1110  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1111  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1113  const auto number_units = translateScalarRex(rex_function->getOperand(1));
1114  const auto number_units_const =
1115  std::dynamic_pointer_cast<Analyzer::Constant>(number_units);
1116  if (number_units_const && number_units_const->get_is_null()) {
1117  throw std::runtime_error("The 'Interval' argument literal must not be 'null'.");
1118  }
1119  const auto cast_number_units = number_units->add_cast(SQLTypeInfo(kBIGINT, false));
1120  const auto datetime = translateScalarRex(rex_function->getOperand(2));
1121  const auto& datetime_ti = datetime->get_type_info();
1122  if (datetime_ti.get_type() == kTIME) {
1123  throw std::runtime_error("DateAdd operation not supported for TIME.");
1124  }
1125  const auto& field = to_dateadd_field(*timeunit_lit->get_constval().stringval);
1126  const int dim = datetime_ti.get_dimension();
1127  return makeExpr<Analyzer::DateaddExpr>(
1128  SQLTypeInfo(kTIMESTAMP, dim, 0, false), field, cast_number_units, datetime);
1129 }
1130 
1131 namespace {
1132 
1134  CHECK(op == kPLUS);
1135  return "DATETIME_PLUS"s;
1136 }
1137 
1138 } // namespace
1139 
1140 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateDatePlusMinus(
1141  const RexOperator* rex_operator) const {
1142  if (rex_operator->size() != 2) {
1143  return nullptr;
1144  }
1145  const auto datetime = translateScalarRex(rex_operator->getOperand(0));
1146  const auto datetime_ti = datetime->get_type_info();
1147  if (!datetime_ti.is_timestamp() && !datetime_ti.is_date()) {
1148  if (datetime_ti.get_type() == kTIME) {
1149  throw std::runtime_error("DateTime addition/subtraction not supported for TIME.");
1150  }
1151  return nullptr;
1152  }
1153  const auto rhs = translateScalarRex(rex_operator->getOperand(1));
1154  const auto rhs_ti = rhs->get_type_info();
1155  if (rhs_ti.get_type() == kTIMESTAMP || rhs_ti.get_type() == kDATE) {
1156  if (datetime_ti.is_high_precision_timestamp() ||
1157  rhs_ti.is_high_precision_timestamp()) {
1158  throw std::runtime_error(
1159  "High Precision timestamps are not supported for TIMESTAMPDIFF operation. "
1160  "Use "
1161  "DATEDIFF.");
1162  }
1163  auto bigint_ti = SQLTypeInfo(kBIGINT, false);
1164  const auto& rex_operator_ti = rex_operator->getType();
1165  const auto datediff_field =
1166  (rex_operator_ti.get_type() == kINTERVAL_DAY_TIME) ? dtSECOND : dtMONTH;
1167  auto result =
1168  makeExpr<Analyzer::DatediffExpr>(bigint_ti, datediff_field, rhs, datetime);
1169  // multiply 1000 to result since expected result should be in millisecond precision.
1170  if (rex_operator_ti.get_type() == kINTERVAL_DAY_TIME) {
1171  return makeExpr<Analyzer::BinOper>(bigint_ti.get_type(),
1172  kMULTIPLY,
1173  kONE,
1174  result,
1175  makeNumericConstant(bigint_ti, 1000));
1176  } else {
1177  return result;
1178  }
1179  }
1180  const auto op = rex_operator->getOperator();
1181  if (op == kPLUS) {
1182  std::vector<std::shared_ptr<Analyzer::Expr>> args = {datetime, rhs};
1183  auto dt_plus = makeExpr<Analyzer::FunctionOper>(
1184  datetime_ti, get_datetimeplus_rewrite_funcname(op), args);
1185  const auto date_trunc = rewrite_to_date_trunc(dt_plus.get());
1186  if (date_trunc) {
1187  return date_trunc;
1188  }
1189  }
1190  const auto interval = fold_expr(rhs.get());
1191  auto interval_ti = interval->get_type_info();
1192  auto bigint_ti = SQLTypeInfo(kBIGINT, false);
1193  const auto interval_lit = std::dynamic_pointer_cast<Analyzer::Constant>(interval);
1194  if (interval_ti.get_type() == kINTERVAL_DAY_TIME) {
1195  std::shared_ptr<Analyzer::Expr> interval_sec;
1196  if (interval_lit) {
1197  interval_sec =
1198  makeNumericConstant(bigint_ti,
1199  (op == kMINUS ? -interval_lit->get_constval().bigintval
1200  : interval_lit->get_constval().bigintval) /
1201  1000);
1202  } else {
1203  interval_sec = makeExpr<Analyzer::BinOper>(bigint_ti.get_type(),
1204  kDIVIDE,
1205  kONE,
1206  interval,
1207  makeNumericConstant(bigint_ti, 1000));
1208  if (op == kMINUS) {
1209  interval_sec =
1210  std::make_shared<Analyzer::UOper>(bigint_ti, false, kUMINUS, interval_sec);
1211  }
1212  }
1213  return makeExpr<Analyzer::DateaddExpr>(datetime_ti, daSECOND, interval_sec, datetime);
1214  }
1215  CHECK(interval_ti.get_type() == kINTERVAL_YEAR_MONTH);
1216  const auto interval_months = op == kMINUS ? std::make_shared<Analyzer::UOper>(
1217  bigint_ti, false, kUMINUS, interval)
1218  : interval;
1219  return makeExpr<Analyzer::DateaddExpr>(datetime_ti, daMONTH, interval_months, datetime);
1220 }
1221 
1222 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateDatediff(
1223  const RexFunctionOperator* rex_function) const {
1224  CHECK_EQ(size_t(3), rex_function->size());
1225  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1226  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1228  const auto start = translateScalarRex(rex_function->getOperand(1));
1229  const auto end = translateScalarRex(rex_function->getOperand(2));
1230  const auto field = to_datediff_field(*timeunit_lit->get_constval().stringval);
1231  return makeExpr<Analyzer::DatediffExpr>(SQLTypeInfo(kBIGINT, false), field, start, end);
1232 }
1233 
1234 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateDatepart(
1235  const RexFunctionOperator* rex_function) const {
1236  CHECK_EQ(size_t(2), rex_function->size());
1237  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1238  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1240  const auto from_expr = translateScalarRex(rex_function->getOperand(1));
1241  return ExtractExpr::generate(
1242  from_expr, to_datepart_field(*timeunit_lit->get_constval().stringval));
1243 }
1244 
1245 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateLength(
1246  const RexFunctionOperator* rex_function) const {
1247  CHECK_EQ(size_t(1), rex_function->size());
1248  const auto str_arg = translateScalarRex(rex_function->getOperand(0));
1249  return makeExpr<Analyzer::CharLengthExpr>(str_arg->decompress(),
1250  rex_function->getName() == "CHAR_LENGTH"sv);
1251 }
1252 
1253 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateKeyForString(
1254  const RexFunctionOperator* rex_function) const {
1255  const auto& args = translateFunctionArgs(rex_function);
1256  CHECK_EQ(size_t(1), args.size());
1257  const auto expr = dynamic_cast<Analyzer::Expr*>(args[0].get());
1258  if (nullptr == expr || !expr->get_type_info().is_string() ||
1259  expr->get_type_info().is_varlen()) {
1260  throw std::runtime_error(rex_function->getName() +
1261  " expects a dictionary encoded text column.");
1262  }
1263  return makeExpr<Analyzer::KeyForStringExpr>(args[0]);
1264 }
1265 
1266 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateSampleRatio(
1267  const RexFunctionOperator* rex_function) const {
1268  CHECK_EQ(size_t(1), rex_function->size());
1269  auto arg = translateScalarRex(rex_function->getOperand(0));
1270  const auto& arg_ti = arg->get_type_info();
1271  if (arg_ti.get_type() != kDOUBLE) {
1272  const auto& double_ti = SQLTypeInfo(kDOUBLE, arg_ti.get_notnull());
1273  arg = arg->add_cast(double_ti);
1274  }
1275  return makeExpr<Analyzer::SampleRatioExpr>(arg);
1276 }
1277 
1278 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateCurrentUser(
1279  const RexFunctionOperator* rex_function) const {
1280  std::string user{"SESSIONLESS_USER"};
1281  if (query_state_) {
1282  user = query_state_->getConstSessionInfo()->get_currentUser().userName;
1283  }
1284  return Parser::UserLiteral::get(user);
1285 }
1286 
1287 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateLower(
1288  const RexFunctionOperator* rex_function) const {
1289  const auto& args = translateFunctionArgs(rex_function);
1290  CHECK_EQ(size_t(1), args.size());
1291  CHECK(args[0]);
1292 
1293  if (args[0]->get_type_info().is_dict_encoded_string() ||
1294  dynamic_cast<Analyzer::Constant*>(args[0].get())) {
1295  return makeExpr<Analyzer::LowerExpr>(args[0]);
1296  }
1297 
1298  throw std::runtime_error(rex_function->getName() +
1299  " expects a dictionary encoded text column or a literal.");
1300 }
1301 
1303  const RexFunctionOperator* rex_function) const {
1304  const auto ret_ti = rex_function->getType();
1305  const auto arg = translateScalarRex(rex_function->getOperand(0));
1306  const auto arg_ti = arg->get_type_info();
1307  if (!arg_ti.is_array()) {
1308  throw std::runtime_error(rex_function->getName() + " expects an array expression.");
1309  }
1310  if (arg_ti.get_subtype() == kARRAY) {
1311  throw std::runtime_error(rex_function->getName() +
1312  " expects one-dimension array expression.");
1313  }
1314  const auto array_size = arg_ti.get_size();
1315  const auto array_elem_size = arg_ti.get_elem_type().get_array_context_logical_size();
1316 
1317  if (array_size > 0) {
1318  if (array_elem_size <= 0) {
1319  throw std::runtime_error(rex_function->getName() +
1320  ": unexpected array element type.");
1321  }
1322  // Return cardinality of a fixed length array
1323  return makeNumericConstant(ret_ti, array_size / array_elem_size);
1324  }
1325  // Variable length array cardinality will be calculated at runtime
1326  return makeExpr<Analyzer::CardinalityExpr>(arg);
1327 }
1328 
1329 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateItem(
1330  const RexFunctionOperator* rex_function) const {
1331  CHECK_EQ(size_t(2), rex_function->size());
1332  const auto base = translateScalarRex(rex_function->getOperand(0));
1333  const auto index = translateScalarRex(rex_function->getOperand(1));
1334  return makeExpr<Analyzer::BinOper>(
1335  base->get_type_info().get_elem_type(), false, kARRAY_AT, kONE, base, index);
1336 }
1337 
1338 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateCurrentDate() const {
1339  constexpr bool is_null = false;
1340  Datum datum;
1341  datum.bigintval = now_ - now_ % (24 * 60 * 60); // Assumes 0 < now_.
1342  return makeExpr<Analyzer::Constant>(kDATE, is_null, datum);
1343 }
1344 
1345 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateCurrentTime() const {
1346  constexpr bool is_null = false;
1347  Datum datum;
1348  datum.bigintval = now_ % (24 * 60 * 60); // Assumes 0 < now_.
1349  return makeExpr<Analyzer::Constant>(kTIME, is_null, datum);
1350 }
1351 
1352 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateCurrentTimestamp() const {
1354 }
1355 
1356 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateDatetime(
1357  const RexFunctionOperator* rex_function) const {
1358  CHECK_EQ(size_t(1), rex_function->size());
1359  const auto arg = translateScalarRex(rex_function->getOperand(0));
1360  const auto arg_lit = std::dynamic_pointer_cast<Analyzer::Constant>(arg);
1361  const std::string datetime_err{R"(Only DATETIME('NOW') supported for now.)"};
1362  if (!arg_lit || arg_lit->get_is_null()) {
1363  throw std::runtime_error(datetime_err);
1364  }
1365  CHECK(arg_lit->get_type_info().is_string());
1366  if (*arg_lit->get_constval().stringval != "NOW"sv) {
1367  throw std::runtime_error(datetime_err);
1368  }
1369  return translateCurrentTimestamp();
1370 }
1371 
1372 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateAbs(
1373  const RexFunctionOperator* rex_function) const {
1374  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1375  expr_list;
1376  CHECK_EQ(size_t(1), rex_function->size());
1377  const auto operand = translateScalarRex(rex_function->getOperand(0));
1378  const auto& operand_ti = operand->get_type_info();
1379  CHECK(operand_ti.is_number());
1380  const auto zero = makeNumericConstant(operand_ti, 0);
1381  const auto lt_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kLT, kONE, operand, zero);
1382  const auto uminus_operand =
1383  makeExpr<Analyzer::UOper>(operand_ti.get_type(), kUMINUS, operand);
1384  expr_list.emplace_back(lt_zero, uminus_operand);
1385  return makeExpr<Analyzer::CaseExpr>(operand_ti, false, expr_list, operand);
1386 }
1387 
1388 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateSign(
1389  const RexFunctionOperator* rex_function) const {
1390  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1391  expr_list;
1392  CHECK_EQ(size_t(1), rex_function->size());
1393  const auto operand = translateScalarRex(rex_function->getOperand(0));
1394  const auto& operand_ti = operand->get_type_info();
1395  CHECK(operand_ti.is_number());
1396  const auto zero = makeNumericConstant(operand_ti, 0);
1397  const auto lt_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kLT, kONE, operand, zero);
1398  expr_list.emplace_back(lt_zero, makeNumericConstant(operand_ti, -1));
1399  const auto eq_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kEQ, kONE, operand, zero);
1400  expr_list.emplace_back(eq_zero, makeNumericConstant(operand_ti, 0));
1401  const auto gt_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kGT, kONE, operand, zero);
1402  expr_list.emplace_back(gt_zero, makeNumericConstant(operand_ti, 1));
1403  return makeExpr<Analyzer::CaseExpr>(
1404  operand_ti,
1405  false,
1406  expr_list,
1407  makeExpr<Analyzer::Constant>(operand_ti, true, Datum{0}));
1408 }
1409 
1410 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateOffsetInFragment() const {
1411  return makeExpr<Analyzer::OffsetInFragment>();
1412 }
1413 
1415  const RexFunctionOperator* rex_function) const {
1416  if (rex_function->getType().get_subtype() == kNULLT) {
1417  auto sql_type = rex_function->getType();
1418  CHECK(sql_type.get_type() == kARRAY);
1419 
1420  // FIX-ME: Deal with NULL arrays
1421  auto translated_function_args(translateFunctionArgs(rex_function));
1422  if (translated_function_args.size() > 0) {
1423  const auto first_element_logical_type =
1424  get_nullable_logical_type_info(translated_function_args[0]->get_type_info());
1425 
1426  auto diff_elem_itr =
1427  std::find_if(translated_function_args.begin(),
1428  translated_function_args.end(),
1429  [first_element_logical_type](const auto expr) {
1430  return first_element_logical_type !=
1431  get_nullable_logical_type_info(expr->get_type_info());
1432  });
1433  if (diff_elem_itr != translated_function_args.end()) {
1434  throw std::runtime_error(
1435  "Element " +
1436  std::to_string(diff_elem_itr - translated_function_args.begin()) +
1437  " is not of the same type as other elements of the array. Consider casting "
1438  "to force this condition.\nElement Type: " +
1439  get_nullable_logical_type_info((*diff_elem_itr)->get_type_info())
1440  .to_string() +
1441  "\nArray type: " + first_element_logical_type.to_string());
1442  }
1443 
1444  if (first_element_logical_type.is_string() &&
1445  !first_element_logical_type.is_dict_encoded_string()) {
1446  sql_type.set_subtype(first_element_logical_type.get_type());
1447  sql_type.set_compression(kENCODING_FIXED);
1448  } else if (first_element_logical_type.is_dict_encoded_string()) {
1449  sql_type.set_subtype(first_element_logical_type.get_type());
1450  sql_type.set_comp_param(TRANSIENT_DICT_ID);
1451  } else {
1452  sql_type.set_subtype(first_element_logical_type.get_type());
1453  sql_type.set_scale(first_element_logical_type.get_scale());
1454  sql_type.set_precision(first_element_logical_type.get_precision());
1455  }
1456 
1457  return makeExpr<Analyzer::ArrayExpr>(sql_type, translated_function_args);
1458  } else {
1459  // defaulting to valid sub-type for convenience
1460  sql_type.set_subtype(kBOOLEAN);
1461  return makeExpr<Analyzer::ArrayExpr>(sql_type, translated_function_args);
1462  }
1463  } else {
1464  return makeExpr<Analyzer::ArrayExpr>(rex_function->getType(),
1465  translateFunctionArgs(rex_function));
1466  }
1467 }
1468 
1469 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateFunction(
1470  const RexFunctionOperator* rex_function) const {
1471  if (func_resolve(rex_function->getName(), "LIKE"sv, "PG_ILIKE"sv)) {
1472  return translateLike(rex_function);
1473  }
1474  if (rex_function->getName() == "REGEXP_LIKE"sv) {
1475  return translateRegexp(rex_function);
1476  }
1477  if (rex_function->getName() == "LIKELY"sv) {
1478  return translateLikely(rex_function);
1479  }
1480  if (rex_function->getName() == "UNLIKELY"sv) {
1481  return translateUnlikely(rex_function);
1482  }
1483  if (func_resolve(rex_function->getName(), "PG_EXTRACT"sv, "PG_DATE_TRUNC"sv)) {
1484  return translateExtract(rex_function);
1485  }
1486  if (rex_function->getName() == "DATEADD"sv) {
1487  return translateDateadd(rex_function);
1488  }
1489  if (rex_function->getName() == "DATEDIFF"sv) {
1490  return translateDatediff(rex_function);
1491  }
1492  if (rex_function->getName() == "DATEPART"sv) {
1493  return translateDatepart(rex_function);
1494  }
1495  if (func_resolve(rex_function->getName(), "LENGTH"sv, "CHAR_LENGTH"sv)) {
1496  return translateLength(rex_function);
1497  }
1498  if (rex_function->getName() == "KEY_FOR_STRING"sv) {
1499  return translateKeyForString(rex_function);
1500  }
1501  if (rex_function->getName() == "WIDTH_BUCKET"sv) {
1502  return translateWidthBucket(rex_function);
1503  }
1504  if (rex_function->getName() == "SAMPLE_RATIO"sv) {
1505  return translateSampleRatio(rex_function);
1506  }
1507  if (rex_function->getName() == "CURRENT_USER"sv) {
1508  return translateCurrentUser(rex_function);
1509  }
1510  if (g_enable_experimental_string_functions && rex_function->getName() == "LOWER"sv) {
1511  return translateLower(rex_function);
1512  }
1513  if (func_resolve(rex_function->getName(), "CARDINALITY"sv, "ARRAY_LENGTH"sv)) {
1514  return translateCardinality(rex_function);
1515  }
1516  if (rex_function->getName() == "ITEM"sv) {
1517  return translateItem(rex_function);
1518  }
1519  if (rex_function->getName() == "CURRENT_DATE"sv) {
1520  return translateCurrentDate();
1521  }
1522  if (rex_function->getName() == "CURRENT_TIME"sv) {
1523  return translateCurrentTime();
1524  }
1525  if (rex_function->getName() == "CURRENT_TIMESTAMP"sv) {
1526  return translateCurrentTimestamp();
1527  }
1528  if (rex_function->getName() == "NOW"sv) {
1529  return translateCurrentTimestamp();
1530  }
1531  if (rex_function->getName() == "DATETIME"sv) {
1532  return translateDatetime(rex_function);
1533  }
1534  if (func_resolve(rex_function->getName(), "usTIMESTAMP"sv, "nsTIMESTAMP"sv)) {
1535  return translateHPTLiteral(rex_function);
1536  }
1537  if (rex_function->getName() == "ABS"sv) {
1538  return translateAbs(rex_function);
1539  }
1540  if (rex_function->getName() == "SIGN"sv) {
1541  return translateSign(rex_function);
1542  }
1543  if (func_resolve(rex_function->getName(), "CEIL"sv, "FLOOR"sv)) {
1544  return makeExpr<Analyzer::FunctionOperWithCustomTypeHandling>(
1545  rex_function->getType(),
1546  rex_function->getName(),
1547  translateFunctionArgs(rex_function));
1548  } else if (rex_function->getName() == "ROUND"sv) {
1549  std::vector<std::shared_ptr<Analyzer::Expr>> args =
1550  translateFunctionArgs(rex_function);
1551 
1552  if (rex_function->size() == 1) {
1553  // push a 0 constant if 2nd operand is missing.
1554  // this needs to be done as calcite returns
1555  // only the 1st operand without defaulting the 2nd one
1556  // when the user did not specify the 2nd operand.
1557  SQLTypes t = kSMALLINT;
1558  Datum d;
1559  d.smallintval = 0;
1560  args.push_back(makeExpr<Analyzer::Constant>(t, false, d));
1561  }
1562 
1563  // make sure we have only 2 operands
1564  CHECK(args.size() == 2);
1565 
1566  if (!args[0]->get_type_info().is_number()) {
1567  throw std::runtime_error("Only numeric 1st operands are supported");
1568  }
1569 
1570  // the 2nd operand does not need to be a constant
1571  // it can happily reference another integer column
1572  if (!args[1]->get_type_info().is_integer()) {
1573  throw std::runtime_error("Only integer 2nd operands are supported");
1574  }
1575 
1576  // Calcite may upcast decimals in a way that is
1577  // incompatible with the extension function input. Play it safe and stick with the
1578  // argument type instead.
1579  const SQLTypeInfo ret_ti = args[0]->get_type_info().is_decimal()
1580  ? args[0]->get_type_info()
1581  : rex_function->getType();
1582 
1583  return makeExpr<Analyzer::FunctionOperWithCustomTypeHandling>(
1584  ret_ti, rex_function->getName(), args);
1585  }
1586  if (rex_function->getName() == "DATETIME_PLUS"sv) {
1587  auto dt_plus = makeExpr<Analyzer::FunctionOper>(rex_function->getType(),
1588  rex_function->getName(),
1589  translateFunctionArgs(rex_function));
1590  const auto date_trunc = rewrite_to_date_trunc(dt_plus.get());
1591  if (date_trunc) {
1592  return date_trunc;
1593  }
1594  return translateDateadd(rex_function);
1595  }
1596  if (rex_function->getName() == "/INT"sv) {
1597  CHECK_EQ(size_t(2), rex_function->size());
1598  std::shared_ptr<Analyzer::Expr> lhs = translateScalarRex(rex_function->getOperand(0));
1599  std::shared_ptr<Analyzer::Expr> rhs = translateScalarRex(rex_function->getOperand(1));
1600  const auto rhs_lit = std::dynamic_pointer_cast<Analyzer::Constant>(rhs);
1601  return Parser::OperExpr::normalize(kDIVIDE, kONE, lhs, rhs);
1602  }
1603  if (rex_function->getName() == "Reinterpret"sv) {
1604  CHECK_EQ(size_t(1), rex_function->size());
1605  return translateScalarRex(rex_function->getOperand(0));
1606  }
1607  if (func_resolve(rex_function->getName(),
1608  "ST_X"sv,
1609  "ST_Y"sv,
1610  "ST_XMin"sv,
1611  "ST_YMin"sv,
1612  "ST_XMax"sv,
1613  "ST_YMax"sv,
1614  "ST_NRings"sv,
1615  "ST_NPoints"sv,
1616  "ST_Length"sv,
1617  "ST_Perimeter"sv,
1618  "ST_Area"sv,
1619  "ST_SRID"sv,
1620  "MapD_GeoPolyBoundsPtr"sv /* deprecated */,
1621  "MapD_GeoPolyBoundsPtr"sv /* deprecated */,
1622  "OmniSci_Geo_PolyBoundsPtr"sv,
1623  "OmniSci_Geo_PolyRenderGroup"sv)) {
1624  CHECK_EQ(rex_function->size(), size_t(1));
1625  return translateUnaryGeoFunction(rex_function);
1626  }
1627  if (func_resolve(rex_function->getName(),
1628  "convert_meters_to_pixel_width"sv,
1629  "convert_meters_to_pixel_height"sv,
1630  "is_point_in_view"sv,
1631  "is_point_size_in_view"sv)) {
1632  return translateFunctionWithGeoArg(rex_function);
1633  }
1634  if (func_resolve(rex_function->getName(),
1635  "ST_Distance"sv,
1636  "ST_MaxDistance"sv,
1637  "ST_Intersects"sv,
1638  "ST_Disjoint"sv,
1639  "ST_Contains"sv,
1640  "ST_Overlaps"sv,
1641  "ST_Approx_Overlaps"sv,
1642  "ST_Within"sv)) {
1643  CHECK_EQ(rex_function->size(), size_t(2));
1644  return translateBinaryGeoFunction(rex_function);
1645  }
1646  if (func_resolve(rex_function->getName(), "ST_DWithin"sv, "ST_DFullyWithin"sv)) {
1647  CHECK_EQ(rex_function->size(), size_t(3));
1648  return translateTernaryGeoFunction(rex_function);
1649  }
1650  if (rex_function->getName() == "OFFSET_IN_FRAGMENT"sv) {
1651  CHECK_EQ(size_t(0), rex_function->size());
1652  return translateOffsetInFragment();
1653  }
1654  if (rex_function->getName() == "ARRAY"sv) {
1655  // Var args; currently no check. Possible fix-me -- can array have 0 elements?
1656  return translateArrayFunction(rex_function);
1657  }
1658  if (func_resolve(rex_function->getName(),
1659  "ST_GeomFromText"sv,
1660  "ST_GeogFromText"sv,
1661  "ST_Centroid"sv,
1662  "ST_SetSRID"sv,
1663  "ST_Point"sv, // TODO: where should this and below live?
1664  "ST_PointN"sv,
1665  "ST_StartPoint"sv,
1666  "ST_EndPoint"sv,
1667  "ST_Transform"sv)) {
1668  SQLTypeInfo ti;
1669  return translateGeoProjection(rex_function, ti, false);
1670  }
1671  if (func_resolve(rex_function->getName(),
1672  "ST_Intersection"sv,
1673  "ST_Difference"sv,
1674  "ST_Union"sv,
1675  "ST_Buffer"sv)) {
1676  SQLTypeInfo ti;
1677  return translateGeoBinaryConstructor(rex_function, ti, false);
1678  }
1679  if (func_resolve(rex_function->getName(), "ST_IsEmpty"sv, "ST_IsValid"sv)) {
1680  SQLTypeInfo ti;
1681  return translateGeoPredicate(rex_function, ti, false);
1682  }
1683 
1684  auto arg_expr_list = translateFunctionArgs(rex_function);
1685  if (rex_function->getName() == std::string("||") ||
1686  rex_function->getName() == std::string("SUBSTRING")) {
1687  SQLTypeInfo ret_ti(kTEXT, false);
1688  return makeExpr<Analyzer::FunctionOper>(
1689  ret_ti, rex_function->getName(), arg_expr_list);
1690  }
1691  // Reset possibly wrong return type of rex_function to the return
1692  // type of the optimal valid implementation. The return type can be
1693  // wrong in the case of multiple implementations of UDF functions
1694  // that have different return types but Calcite specifies the return
1695  // type according to the first implementation.
1696  SQLTypeInfo ret_ti;
1697  try {
1698  auto ext_func_sig = bind_function(rex_function->getName(), arg_expr_list);
1699 
1700  auto ext_func_args = ext_func_sig.getArgs();
1701  CHECK_EQ(arg_expr_list.size(), ext_func_args.size());
1702  for (size_t i = 0; i < arg_expr_list.size(); i++) {
1703  // fold casts on constants
1704  if (auto constant =
1705  std::dynamic_pointer_cast<Analyzer::Constant>(arg_expr_list[i])) {
1706  auto ext_func_arg_ti = ext_arg_type_to_type_info(ext_func_args[i]);
1707  if (ext_func_arg_ti != arg_expr_list[i]->get_type_info()) {
1708  arg_expr_list[i] = constant->add_cast(ext_func_arg_ti);
1709  }
1710  }
1711  }
1712 
1713  ret_ti = ext_arg_type_to_type_info(ext_func_sig.getRet());
1714  } catch (ExtensionFunctionBindingError& e) {
1715  LOG(WARNING) << "RelAlgTranslator::translateFunction: " << e.what();
1716  throw;
1717  }
1718 
1719  // By default, the extension function type will not allow nulls. If one of the arguments
1720  // is nullable, the extension function must also explicitly allow nulls.
1721  bool arguments_not_null = true;
1722  for (const auto& arg_expr : arg_expr_list) {
1723  if (!arg_expr->get_type_info().get_notnull()) {
1724  arguments_not_null = false;
1725  break;
1726  }
1727  }
1728  ret_ti.set_notnull(arguments_not_null);
1729 
1730  return makeExpr<Analyzer::FunctionOper>(ret_ti, rex_function->getName(), arg_expr_list);
1731 }
1732 
1733 namespace {
1734 
1735 std::vector<Analyzer::OrderEntry> translate_collation(
1736  const std::vector<SortField>& sort_fields) {
1737  std::vector<Analyzer::OrderEntry> collation;
1738  for (size_t i = 0; i < sort_fields.size(); ++i) {
1739  const auto& sort_field = sort_fields[i];
1740  collation.emplace_back(i,
1741  sort_field.getSortDir() == SortDirection::Descending,
1742  sort_field.getNullsPosition() == NullSortedPosition::First);
1743  }
1744  return collation;
1745 }
1746 
1748  const RexWindowFunctionOperator::RexWindowBound& window_bound) {
1749  return window_bound.unbounded && window_bound.preceding && !window_bound.following &&
1750  !window_bound.is_current_row && !window_bound.offset &&
1751  window_bound.order_key == 0;
1752 }
1753 
1754 bool supported_upper_bound(const RexWindowFunctionOperator* rex_window_function) {
1755  const auto& window_bound = rex_window_function->getUpperBound();
1756  const bool to_current_row = !window_bound.unbounded && !window_bound.preceding &&
1757  !window_bound.following && window_bound.is_current_row &&
1758  !window_bound.offset && window_bound.order_key == 1;
1759  switch (rex_window_function->getKind()) {
1764  return to_current_row;
1765  }
1766  default: {
1767  return rex_window_function->getOrderKeys().empty()
1768  ? (window_bound.unbounded && !window_bound.preceding &&
1769  window_bound.following && !window_bound.is_current_row &&
1770  !window_bound.offset && window_bound.order_key == 2)
1771  : to_current_row;
1772  }
1773  }
1774 }
1775 
1776 } // namespace
1777 
1778 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateWindowFunction(
1779  const RexWindowFunctionOperator* rex_window_function) const {
1780  if (!supported_lower_bound(rex_window_function->getLowerBound()) ||
1781  !supported_upper_bound(rex_window_function) ||
1782  ((rex_window_function->getKind() == SqlWindowFunctionKind::ROW_NUMBER) !=
1783  rex_window_function->isRows())) {
1784  throw std::runtime_error("Frame specification not supported");
1785  }
1786  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1787  for (size_t i = 0; i < rex_window_function->size(); ++i) {
1788  args.push_back(translateScalarRex(rex_window_function->getOperand(i)));
1789  }
1790  std::vector<std::shared_ptr<Analyzer::Expr>> partition_keys;
1791  for (const auto& partition_key : rex_window_function->getPartitionKeys()) {
1792  partition_keys.push_back(translateScalarRex(partition_key.get()));
1793  }
1794  std::vector<std::shared_ptr<Analyzer::Expr>> order_keys;
1795  for (const auto& order_key : rex_window_function->getOrderKeys()) {
1796  order_keys.push_back(translateScalarRex(order_key.get()));
1797  }
1798  auto ti = rex_window_function->getType();
1799  if (window_function_is_value(rex_window_function->getKind())) {
1800  CHECK_GE(args.size(), 1u);
1801  ti = args.front()->get_type_info();
1802  }
1803  return makeExpr<Analyzer::WindowFunction>(
1804  ti,
1805  rex_window_function->getKind(),
1806  args,
1807  partition_keys,
1808  order_keys,
1809  translate_collation(rex_window_function->getCollation()));
1810 }
1811 
1813  const RexFunctionOperator* rex_function) const {
1814  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1815  for (size_t i = 0; i < rex_function->size(); ++i) {
1816  args.push_back(translateScalarRex(rex_function->getOperand(i)));
1817  }
1818  return args;
1819 }
1820 
1822  const std::shared_ptr<Analyzer::Expr> qual_expr) {
1823  CHECK(qual_expr);
1824  auto bin_oper = std::dynamic_pointer_cast<const Analyzer::BinOper>(qual_expr);
1825  if (!bin_oper) {
1826  const auto rewritten_qual_expr = rewrite_expr(qual_expr.get());
1827  return {{}, {rewritten_qual_expr ? rewritten_qual_expr : qual_expr}};
1828  }
1829 
1830  if (bin_oper->get_optype() == kAND) {
1831  const auto lhs_cf = qual_to_conjunctive_form(bin_oper->get_own_left_operand());
1832  const auto rhs_cf = qual_to_conjunctive_form(bin_oper->get_own_right_operand());
1833  auto simple_quals = lhs_cf.simple_quals;
1834  simple_quals.insert(
1835  simple_quals.end(), rhs_cf.simple_quals.begin(), rhs_cf.simple_quals.end());
1836  auto quals = lhs_cf.quals;
1837  quals.insert(quals.end(), rhs_cf.quals.begin(), rhs_cf.quals.end());
1838  return {simple_quals, quals};
1839  }
1840  int rte_idx{0};
1841  const auto simple_qual = bin_oper->normalize_simple_predicate(rte_idx);
1842  return simple_qual ? QualsConjunctiveForm{{simple_qual}, {}}
1843  : QualsConjunctiveForm{{}, {qual_expr}};
1844 }
1845 
1846 std::vector<std::shared_ptr<Analyzer::Expr>> qual_to_disjunctive_form(
1847  const std::shared_ptr<Analyzer::Expr>& qual_expr) {
1848  CHECK(qual_expr);
1849  const auto bin_oper = std::dynamic_pointer_cast<const Analyzer::BinOper>(qual_expr);
1850  if (!bin_oper) {
1851  const auto rewritten_qual_expr = rewrite_expr(qual_expr.get());
1852  return {rewritten_qual_expr ? rewritten_qual_expr : qual_expr};
1853  }
1854  if (bin_oper->get_optype() == kOR) {
1855  const auto lhs_df = qual_to_disjunctive_form(bin_oper->get_own_left_operand());
1856  const auto rhs_df = qual_to_disjunctive_form(bin_oper->get_own_right_operand());
1857  auto quals = lhs_df;
1858  quals.insert(quals.end(), rhs_df.begin(), rhs_df.end());
1859  return quals;
1860  }
1861  return {qual_expr};
1862 }
1863 
1864 std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateHPTLiteral(
1865  const RexFunctionOperator* rex_function) const {
1866  /* since calcite uses Avatica package called DateTimeUtils to parse timestamp strings.
1867  Therefore any string having fractional seconds more 3 places after the decimal
1868  (milliseconds) will get truncated to 3 decimal places, therefore we lose precision
1869  (us|ns). Issue: [BE-2461] Here we are hijacking literal cast to Timestamp(6|9) from
1870  calcite and translating them to generate our own casts.
1871  */
1872  CHECK_EQ(size_t(1), rex_function->size());
1873  const auto operand = translateScalarRex(rex_function->getOperand(0));
1874  const auto& operand_ti = operand->get_type_info();
1875  const auto& target_ti = rex_function->getType();
1876  if (!operand_ti.is_string()) {
1877  throw std::runtime_error(
1878  "High precision timestamp cast argument must be a string. Input type is: " +
1879  operand_ti.get_type_name());
1880  } else if (!target_ti.is_high_precision_timestamp()) {
1881  throw std::runtime_error(
1882  "Cast target type should be high precision timestamp. Input type is: " +
1883  target_ti.get_type_name());
1884  } else if (target_ti.get_dimension() != 6 && target_ti.get_dimension() != 9) {
1885  throw std::runtime_error(
1886  "Cast target type should be TIMESTAMP(6|9). Input type is: TIMESTAMP(" +
1887  std::to_string(target_ti.get_dimension()) + ")");
1888  } else {
1889  return operand->add_cast(target_ti);
1890  }
1891 }
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:69
const RexScalar * getThen(const size_t idx) const
const std::vector< JoinType > join_types_
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:330
SQLAgg
Definition: sqldefs.h:71
#define CHECK_EQ(x, y)
Definition: Logger.h:217
auto func_resolve
std::shared_ptr< Analyzer::Expr > translateOffsetInFragment() const
static std::shared_ptr< Analyzer::Expr > get(const std::string &)
Definition: ParserNode.cpp:210
bool g_enable_watchdog
std::shared_ptr< Analyzer::Expr > translateCurrentTimestamp() const
SQLAgg getKind() const
Definition: sqltypes.h:49
std::shared_ptr< Analyzer::Expr > translateRegexp(const RexFunctionOperator *) const
bool supported_lower_bound(const RexWindowFunctionOperator::RexWindowBound &window_bound)
SQLTypes
Definition: sqltypes.h:38
size_t getOperand(size_t idx) const
const Executor * executor_
std::shared_ptr< Analyzer::Expr > translateUnlikely(const RexFunctionOperator *) const
const RexScalar * getElse() const
SQLQualifier
Definition: sqldefs.h:69
static std::shared_ptr< Analyzer::Expr > analyzeValue(const int64_t intval)
Definition: ParserNode.cpp:135
std::shared_ptr< Analyzer::Expr > translateFunction(const RexFunctionOperator *) const
SQLTypeInfo get_nullable_logical_type_info(const SQLTypeInfo &type_info)
Definition: sqltypes.h:952
#define LOG(tag)
Definition: Logger.h:203
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const SQLTypeInfo & getType() const
size_t size() const
const RexScalar * getOperand(const size_t idx) const
std::shared_ptr< Analyzer::Expr > translateUoper(const RexOperator *) const
HOST DEVICE int get_scale() const
Definition: sqltypes.h:334
const std::vector< SortField > & getCollation() const
SQLOps
Definition: sqldefs.h:29
std::shared_ptr< Analyzer::Expr > translateDateadd(const RexFunctionOperator *) const
int8_t boolval
Definition: sqltypes.h:211
Definition: sqldefs.h:38
#define CHECK_GE(x, y)
Definition: Logger.h:222
std::shared_ptr< Analyzer::Expr > translateAbs(const RexFunctionOperator *) const
Definition: sqldefs.h:49
Definition: sqldefs.h:30
const RexScalar * getWhen(const size_t idx) const
std::shared_ptr< Analyzer::Expr > ExpressionPtr
Definition: Analyzer.h:180
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:41
SQLTypeInfo get_agg_type(const SQLAgg agg_kind, const Analyzer::Expr *arg_expr)
std::shared_ptr< Analyzer::Expr > translateItem(const RexFunctionOperator *) const
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:329
QualsConjunctiveForm qual_to_conjunctive_form(const std::shared_ptr< Analyzer::Expr > qual_expr)
bool is_number() const
Definition: sqltypes.h:509
#define CHECK_GT(x, y)
Definition: Logger.h:221
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)
bool is_time() const
Definition: sqltypes.h:510
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 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 >)
Definition: ParserNode.cpp:958
std::shared_ptr< Analyzer::Expr > translateGeoOverlapsOper(const RexOperator *) const
Definition: sqldefs.h:73
std::shared_ptr< Analyzer::Expr > translateLower(const RexFunctionOperator *) const
ExtractField to_datepart_field(const std::string &field)
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
unsigned getIndex() const
future< Result > async(Fn &&fn, Args &&...args)
static std::shared_ptr< Analyzer::Expr > translateLiteral(const RexLiteral *)
SQLOps getOperator() const
bool window_function_is_value(const SqlWindowFunctionKind kind)
Definition: WindowContext.h:27
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 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:218
const std::shared_ptr< Analyzer::Expr > generate() 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:656
void set_scale(int s)
Definition: sqltypes.h:424
int64_t bigintval
Definition: sqltypes.h:215
std::shared_ptr< const RexScalar > offset
std::vector< Analyzer::OrderEntry > translate_collation(const std::vector< SortField > &sort_fields)
size_t branchCount() const
std::shared_ptr< Analyzer::Expr > translateCurrentTime() const
Definition: sqldefs.h:37
Definition: sqldefs.h:75
Definition: sqldefs.h:69
int getDatabaseId() const
Definition: Catalog.h:277
int16_t smallintval
Definition: sqltypes.h:213
SQLTypeInfo build_type_info(const SQLTypes sql_type, const int scale, const int precision)
static std::shared_ptr< Analyzer::Expr > analyzeValue(const std::string &)
Definition: ParserNode.cpp:120
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:511
const std::vector< LeafHostInfo > & getStringDictionaryHosts() const
Definition: Catalog.cpp:1573
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:1628
const std::unordered_map< const RelAlgNode *, int > input_to_nest_level_
#define UNLIKELY(x)
Definition: likely.h:25
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)
Definition: ParserNode.cpp:286
std::pair< std::shared_ptr< Analyzer::Expr >, SQLQualifier > get_quantified_rhs(const RexScalar *rex_scalar, const RelAlgTranslator &translator)
Definition: sqldefs.h:34
#define CHECK_LT(x, y)
Definition: Logger.h:219
Definition: sqltypes.h:52
Definition: sqltypes.h:53
Analyzer::ExpressionPtrVector translateFunctionArgs(const RexFunctionOperator *) const
Definition: sqldefs.h:40
Definition: sqldefs.h:69
const ConstRexScalarPtrVector & getPartitionKeys() const
#define TRANSIENT_DICT_ID
Definition: sqltypes.h:259
const RexWindowBound & getLowerBound() const
DEVICE auto lower_bound(ARGS &&...args)
Definition: gpu_enabled.h:78
#define CHECK_LE(x, y)
Definition: Logger.h:220
std::shared_ptr< Analyzer::Expr > translateOverlapsOper(const RexOperator *) 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:561
std::shared_ptr< Analyzer::Expr > translateCurrentUser(const RexFunctionOperator *) const
bool g_enable_experimental_string_functions
std::shared_ptr< Analyzer::Expr > translateSampleRatio(const RexFunctionOperator *) const
SqlWindowFunctionKind getKind() const
std::shared_ptr< Analyzer::Expr > translateLike(const RexFunctionOperator *) const
const RelAlgNode * getSourceNode() const
std::shared_ptr< Analyzer::Expr > translateGeoBinaryConstructor(const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
Definition: sqltypes.h:41
bool supported_upper_bound(const RexWindowFunctionOperator *rex_window_function)
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:160
std::shared_ptr< Analyzer::Expr > translateLikely(const RexFunctionOperator *) const
const RexWindowBound & getUpperBound() const
Definition: sqldefs.h:53
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:196
bool isDistinct() const
void set_notnull(bool n)
Definition: sqltypes.h:426
#define CHECK(condition)
Definition: Logger.h:209
std::shared_ptr< Analyzer::Expr > translateTernaryGeoFunction(const RexFunctionOperator *) const
const ConstRexScalarPtrVector & getOrderKeys() const
char * t
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
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
std::vector< ExpressionPtr > ExpressionPtrVector
Definition: Analyzer.h:182
bool g_cluster
Definition: sqldefs.h:33
std::shared_ptr< Analyzer::Expr > translateCase(const RexCase *) const
std::shared_ptr< Analyzer::Expr > translateFunctionWithGeoArg(const RexFunctionOperator *) const
Definition: sqltypes.h:45
std::shared_ptr< const query_state::QueryState > query_state_
const std::string & getName() const
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:74
int cpu_threads()
Definition: thread_count.h:24
const bool just_explain_
const std::vector< TargetMetaInfo > & getOutputMetainfo() const
bool is_decimal() const
Definition: sqltypes.h:507
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:72
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:1137
Definition: sqldefs.h:39
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)
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:422
#define IS_COMPARISON(X)
Definition: sqldefs.h:57
double doubleval
Definition: sqltypes.h:217
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
std::shared_ptr< Analyzer::Expr > translateGeoPredicate(const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
boost::variant< int64_t, double, float, NullableString > ScalarTargetValue
Definition: TargetValue.h:156
std::shared_ptr< Analyzer::Expr > translateLength(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateExtract(const RexFunctionOperator *) const