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