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