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